docs/man5/
docs/pdf/
docs/txt/
-extras/mini-os/include/mini-os
-extras/mini-os/include/x86/mini-os
-extras/mini-os/include/list.h
-extras/mini-os/mini-os*
+extras/mini-os
+extras/mini-os-remote
install/*
stubdom/autom4te.cache/
stubdom/binutils-*
QEMU_UPSTREAM_URL ?= http://xenbits.xen.org/git-http/qemu-upstream-unstable.git
QEMU_TRADITIONAL_URL ?= http://xenbits.xen.org/git-http/qemu-xen-unstable.git
SEABIOS_UPSTREAM_URL ?= http://xenbits.xen.org/git-http/seabios.git
+MINIOS_UPSTREAM_URL ?= http://xenbits.xen.org/git-http/mini-os.git
else
OVMF_UPSTREAM_URL ?= git://xenbits.xen.org/ovmf.git
QEMU_UPSTREAM_URL ?= git://xenbits.xen.org/qemu-upstream-unstable.git
QEMU_TRADITIONAL_URL ?= git://xenbits.xen.org/qemu-xen-unstable.git
SEABIOS_UPSTREAM_URL ?= git://xenbits.xen.org/seabios.git
+MINIOS_UPSTREAM_URL ?= git://xenbits.xen.org/mini-os.git
endif
OVMF_UPSTREAM_REVISION ?= 447d264115c476142f884af0be287622cd244423
QEMU_UPSTREAM_REVISION ?= master
+MINIOS_UPSTREAM_REVISION ?= 55f7cd7427ef3e7fe3563a3da46d8664a2ed0d6d
+# Thu Jan 29 19:10:04 2015 +0000
+# Mini-OS: standalone build
+
SEABIOS_UPSTREAM_REVISION ?= rel-1.7.5
# Thu May 22 16:59:16 2014 -0400
# python3 fixes for vgabios and csm builds.
export XEN_ROOT=$(CURDIR)
include Config.mk
+.PHONY: mini-os-dir
+mini-os-dir:
+ GIT=$(GIT) $(XEN_ROOT)/scripts/git-checkout.sh \
+ $(MINIOS_UPSTREAM_URL) \
+ $(MINIOS_UPSTREAM_REVISION) \
+ $(XEN_ROOT)/extras/mini-os
+
+.PHONY: mini-os-dir-force-update
+mini-os-dir-force-update: mini-os-dir
+ set -ex; \
+ if [ "$(MINIOS_UPSTREAM_REVISION)" ]; then \
+ cd extras/mini-os-remote; \
+ $(GIT) fetch origin; \
+ $(GIT) reset --hard $(MINIOS_UPSTREAM_REVISION); \
+ fi
+
SUBARCH := $(subst x86_32,i386,$(XEN_TARGET_ARCH))
export XEN_TARGET_ARCH SUBARCH
export DESTDIR
$(MAKE) -C tools build
.PHONY: build-stubdom
-build-stubdom:
+build-stubdom: mini-os-dir
$(MAKE) -C stubdom build
ifeq (x86_64,$(XEN_TARGET_ARCH))
XEN_TARGET_ARCH=x86_32 $(MAKE) -C stubdom pv-grub
$(MAKE) -C tools install
.PHONY: install-stubdom
-install-stubdom: install-tools
+install-stubdom: install-tools mini-os-dir
$(MAKE) -C stubdom install
ifeq (x86_64,$(XEN_TARGET_ARCH))
XEN_TARGET_ARCH=x86_32 $(MAKE) -C stubdom install-grub
bash ./tools/misc/mkrpm $(XEN_ROOT) $$($(MAKE) -C xen xenversion --no-print-directory)
.PHONY: subtree-force-update
-subtree-force-update:
+subtree-force-update: mini-os-dir-force-update
$(MAKE) -C tools subtree-force-update
.PHONY: subtree-force-update-all
-subtree-force-update-all:
+subtree-force-update-all: mini-os-dir-force-update
$(MAKE) -C tools subtree-force-update-all
# Make a source tarball, including qemu sub-trees.
--- /dev/null
+Certain files in this directory are licensed by the GNU
+General Public License version 2 (GPLv2). By default these
+files are not built and linked into MiniOs. Enabling them
+will cause the whole work to become covered by the GPLv2.
+
+The current set of GPLv2 features are:
+CONFIG_TPMFRONT
+CONFIG_TPMBACK
+CONFIG_TPM_TIS
+
+Do not use these if you do not want your MiniOS build to become
+GPL licensed!
+
+Copyright (c) 2009 Citrix Systems, Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
--- /dev/null
+#
+# Compare $(1) and $(2) and replace $(2) with $(1) if they differ
+#
+# Typically $(1) is a newly generated file and $(2) is the target file
+# being regenerated. This prevents changing the timestamp of $(2) only
+# due to being auto regenereated with the same contents.
+define move-if-changed
+ if ! cmp -s $(1) $(2); then mv -f $(1) $(2); else rm -f $(1); fi
+endef
+
+# cc-option: Check if compiler supports first option, else fall back to second.
+#
+# This is complicated by the fact that unrecognised -Wno-* options:
+# (a) are ignored unless the compilation emits a warning; and
+# (b) even then produce a warning rather than an error
+# To handle this we do a test compile, passing the option-under-test, on a code
+# fragment that will always produce a warning (integer assigned to pointer).
+# We then grep for the option-under-test in the compiler's output, the presence
+# of which would indicate an "unrecognized command-line option" warning/error.
+#
+# Usage: cflags-y += $(call cc-option,$(CC),-march=winchip-c6,-march=i586)
+cc-option = $(shell if test -z "`echo 'void*p=1;' | \
+ $(1) $(2) -S -o /dev/null -x c - 2>&1 | grep -- $(2) -`"; \
+ then echo "$(2)"; else echo "$(3)"; fi ;)
+
+# Compatibility with Xen's stubdom build environment. If we are building
+# stubdom, some XEN_ variables are set, set MINIOS_ variables accordingly.
+#
+ifneq ($(XEN_ROOT),)
+MINI-OS_ROOT=$(XEN_ROOT)/extras/mini-os
+else
+MINI-OS_ROOT=$(TOPLEVEL_DIR)
+endif
+export MINI-OS_ROOT
+
+ifneq ($(XEN_TARGET_ARCH),)
+MINIOS_TARGET_ARCH = $(XEN_TARGET_ARCH)
+else
+MINIOS_COMPILE_ARCH ?= $(shell uname -m | sed -e s/i.86/x86_32/ \
+ -e s/i86pc/x86_32/ -e s/amd64/x86_64/ \
+ -e s/armv7.*/arm32/ -e s/armv8.*/arm64/ \
+ -e s/aarch64/arm64/)
+
+MINIOS_TARGET_ARCH ?= $(MINIOS_COMPILE_ARCH)
+endif
+
+libc = $(stubdom)
+
+XEN_INTERFACE_VERSION := 0x00030205
+export XEN_INTERFACE_VERSION
+
+# Try to find out the architecture family TARGET_ARCH_FAM.
+# First check whether x86_... is contained (for x86_32, x86_32y, x86_64).
+# If not x86 then use $(MINIOS_TARGET_ARCH)
+ifeq ($(findstring x86_,$(MINIOS_TARGET_ARCH)),x86_)
+TARGET_ARCH_FAM = x86
+else
+TARGET_ARCH_FAM = $(MINIOS_TARGET_ARCH)
+endif
+
+# The architecture family directory below mini-os.
+TARGET_ARCH_DIR := arch/$(TARGET_ARCH_FAM)
+
+# Export these variables for possible use in architecture dependent makefiles.
+export TARGET_ARCH_DIR
+export TARGET_ARCH_FAM
+
+# This is used for architecture specific links.
+# This can be overwritten from arch specific rules.
+ARCH_LINKS =
+
+# The path pointing to the architecture specific header files.
+ARCH_INC := $(TARGET_ARCH_FAM)
+
+# For possible special header directories.
+# This can be overwritten from arch specific rules.
+EXTRA_INC = $(ARCH_INC)
+
+# Include the architecture family's special makerules.
+# This must be before include minios.mk!
+include $(MINI-OS_ROOT)/$(TARGET_ARCH_DIR)/arch.mk
+
+extra_incl := $(foreach dir,$(EXTRA_INC),-isystem $(MINI-OS_ROOT)/include/$(dir))
+
+DEF_CPPFLAGS += -isystem $(MINI-OS_ROOT)/include
+DEF_CPPFLAGS += -D__MINIOS__
+
+ifeq ($(libc),y)
+DEF_CPPFLAGS += -DHAVE_LIBC
+DEF_CPPFLAGS += -isystem $(MINI-OS_ROOT)/include/posix
+DEF_CPPFLAGS += -isystem $(XEN_ROOT)/tools/xenstore/include
+endif
+
+ifneq ($(LWIPDIR),)
+lwip=y
+DEF_CPPFLAGS += -DHAVE_LWIP
+DEF_CPPFLAGS += -isystem $(LWIPDIR)/src/include
+DEF_CPPFLAGS += -isystem $(LWIPDIR)/src/include/ipv4
+endif
--- /dev/null
+# Common Makefile for mini-os.
+#
+# Every architecture directory below mini-os/arch has to have a
+# Makefile and a arch.mk.
+#
+
+OBJ_DIR=$(CURDIR)
+TOPLEVEL_DIR=$(CURDIR)
+
+ifeq ($(MINIOS_CONFIG),)
+include Config.mk
+else
+EXTRA_DEPS += $(MINIOS_CONFIG)
+include $(MINIOS_CONFIG)
+endif
+
+include $(MINI-OS_ROOT)/config/MiniOS.mk
+
+# Configuration defaults
+CONFIG_START_NETWORK ?= y
+CONFIG_SPARSE_BSS ?= y
+CONFIG_QEMU_XS_ARGS ?= n
+CONFIG_TEST ?= n
+CONFIG_PCIFRONT ?= n
+CONFIG_BLKFRONT ?= y
+CONFIG_TPMFRONT ?= n
+CONFIG_TPM_TIS ?= n
+CONFIG_TPMBACK ?= n
+CONFIG_NETFRONT ?= y
+CONFIG_FBFRONT ?= y
+CONFIG_KBDFRONT ?= y
+CONFIG_CONSFRONT ?= y
+CONFIG_XENBUS ?= y
+CONFIG_XC ?=y
+CONFIG_LWIP ?= $(lwip)
+
+# Export config items as compiler directives
+flags-$(CONFIG_START_NETWORK) += -DCONFIG_START_NETWORK
+flags-$(CONFIG_SPARSE_BSS) += -DCONFIG_SPARSE_BSS
+flags-$(CONFIG_QEMU_XS_ARGS) += -DCONFIG_QEMU_XS_ARGS
+flags-$(CONFIG_PCIFRONT) += -DCONFIG_PCIFRONT
+flags-$(CONFIG_BLKFRONT) += -DCONFIG_BLKFRONT
+flags-$(CONFIG_TPMFRONT) += -DCONFIG_TPMFRONT
+flags-$(CONFIG_TPM_TIS) += -DCONFIG_TPM_TIS
+flags-$(CONFIG_TPMBACK) += -DCONFIG_TPMBACK
+flags-$(CONFIG_NETFRONT) += -DCONFIG_NETFRONT
+flags-$(CONFIG_KBDFRONT) += -DCONFIG_KBDFRONT
+flags-$(CONFIG_FBFRONT) += -DCONFIG_FBFRONT
+flags-$(CONFIG_CONSFRONT) += -DCONFIG_CONSFRONT
+flags-$(CONFIG_XENBUS) += -DCONFIG_XENBUS
+
+DEF_CFLAGS += $(flags-y)
+
+# Symlinks and headers that must be created before building the C files
+GENERATED_HEADERS := include/list.h $(ARCH_LINKS) include/mini-os include/$(TARGET_ARCH_FAM)/mini-os
+
+EXTRA_DEPS += $(GENERATED_HEADERS)
+
+# Include common mini-os makerules.
+include minios.mk
+
+# Set tester flags
+# CFLAGS += -DBLKTEST_WRITE
+
+# Define some default flags for linking.
+LDLIBS :=
+APP_LDLIBS :=
+LDARCHLIB := -L$(OBJ_DIR)/$(TARGET_ARCH_DIR) -l$(ARCH_LIB_NAME)
+LDFLAGS_FINAL := -T $(TARGET_ARCH_DIR)/minios-$(MINIOS_TARGET_ARCH).lds
+
+# Prefix for global API names. All other symbols are localised before
+# linking with EXTRA_OBJS.
+GLOBAL_PREFIX := xenos_
+EXTRA_OBJS =
+
+TARGET := mini-os
+
+# Subdirectories common to mini-os
+SUBDIRS := lib xenbus console
+
+src-$(CONFIG_BLKFRONT) += blkfront.c
+src-$(CONFIG_TPMFRONT) += tpmfront.c
+src-$(CONFIG_TPM_TIS) += tpm_tis.c
+src-$(CONFIG_TPMBACK) += tpmback.c
+src-y += daytime.c
+src-y += events.c
+src-$(CONFIG_FBFRONT) += fbfront.c
+src-y += gntmap.c
+src-y += gnttab.c
+src-y += hypervisor.c
+src-y += kernel.c
+src-y += lock.c
+src-y += main.c
+src-y += mm.c
+src-$(CONFIG_NETFRONT) += netfront.c
+src-$(CONFIG_PCIFRONT) += pcifront.c
+src-y += sched.c
+src-$(CONFIG_TEST) += test.c
+
+src-y += lib/ctype.c
+src-y += lib/math.c
+src-y += lib/printf.c
+src-y += lib/stack_chk_fail.c
+src-y += lib/string.c
+src-y += lib/sys.c
+src-y += lib/xmalloc.c
+src-$(CONFIG_XENBUS) += lib/xs.c
+
+src-$(CONFIG_XENBUS) += xenbus/xenbus.c
+
+src-y += console/console.c
+src-y += console/xencons_ring.c
+src-$(CONFIG_CONSFRONT) += console/xenbus.c
+
+# The common mini-os objects to build.
+APP_OBJS :=
+OBJS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(src-y))
+
+.PHONY: default
+default: $(OBJ_DIR)/$(TARGET)
+
+# Create special architecture specific links. The function arch_links
+# has to be defined in arch.mk (see include above).
+ifneq ($(ARCH_LINKS),)
+$(ARCH_LINKS):
+ $(arch_links)
+endif
+
+include/list.h: include/minios-external/bsd-sys-queue-h-seddery include/minios-external/bsd-sys-queue.h
+ perl $^ --prefix=minios >$@.new
+ $(call move-if-changed,$@.new,$@)
+
+# Used by stubdom's Makefile
+.PHONY: links
+links: $(GENERATED_HEADERS)
+
+include/mini-os:
+ ln -sf . $@
+
+include/$(TARGET_ARCH_FAM)/mini-os:
+ ln -sf . $@
+
+.PHONY: arch_lib
+arch_lib:
+ $(MAKE) --directory=$(TARGET_ARCH_DIR) OBJ_DIR=$(OBJ_DIR)/$(TARGET_ARCH_DIR) || exit 1;
+
+ifeq ($(CONFIG_LWIP),y)
+# lwIP library
+LWC := $(shell find $(LWIPDIR)/src -type f -name '*.c')
+LWC := $(filter-out %6.c %ip6_addr.c %ethernetif.c, $(LWC))
+LWO := $(patsubst %.c,%.o,$(LWC))
+LWO += $(OBJ_DIR)/lwip-arch.o
+ifeq ($(CONFIG_NETFRONT),y)
+LWO += $(OBJ_DIR)/lwip-net.o
+endif
+
+$(OBJ_DIR)/lwip.a: $(LWO)
+ $(RM) $@
+ $(AR) cqs $@ $^
+
+OBJS += $(OBJ_DIR)/lwip.a
+endif
+
+OBJS := $(filter-out $(OBJ_DIR)/lwip%.o $(LWO), $(OBJS))
+
+ifeq ($(libc),y)
+ifeq ($(CONFIG_XC),y)
+APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxc-$(XEN_TARGET_ARCH) -whole-archive -lxenguest -lxenctrl -no-whole-archive
+endif
+APP_LDLIBS += -lpci
+APP_LDLIBS += -lz
+APP_LDLIBS += -lm
+LDLIBS += -lc
+endif
+
+ifneq ($(APP_OBJS)-$(lwip),-y)
+OBJS := $(filter-out $(OBJ_DIR)/daytime.o, $(OBJS))
+endif
+
+$(OBJ_DIR)/$(TARGET)_app.o: $(APP_OBJS) app.lds
+ $(LD) -r -d $(LDFLAGS) -\( $^ -\) $(APP_LDLIBS) --undefined main -o $@
+
+ifneq ($(APP_OBJS),)
+APP_O=$(OBJ_DIR)/$(TARGET)_app.o
+endif
+
+$(OBJ_DIR)/$(TARGET): $(OBJS) $(APP_O) arch_lib
+ $(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(APP_O) $(OBJS) $(LDARCHLIB) $(LDLIBS) -o $@.o
+ $(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o
+ $(LD) $(LDFLAGS) $(LDFLAGS_FINAL) $@.o $(EXTRA_OBJS) -o $@
+ gzip -f -9 -c $@ >$@.gz
+
+.PHONY: clean arch_clean
+
+arch_clean:
+ $(MAKE) --directory=$(TARGET_ARCH_DIR) OBJ_DIR=$(OBJ_DIR)/$(TARGET_ARCH_DIR) clean || exit 1;
+
+clean: arch_clean
+ for dir in $(addprefix $(OBJ_DIR)/,$(SUBDIRS)); do \
+ rm -f $$dir/*.o; \
+ done
+ rm -f include/list.h
+ rm -f $(OBJ_DIR)/*.o *~ $(OBJ_DIR)/core $(OBJ_DIR)/$(TARGET).elf $(OBJ_DIR)/$(TARGET).raw $(OBJ_DIR)/$(TARGET) $(OBJ_DIR)/$(TARGET).gz
+ find . $(OBJ_DIR) -type l | xargs rm -f
+ $(RM) $(OBJ_DIR)/lwip.a $(LWO)
+ rm -f tags TAGS
+
+
+define all_sources
+ ( find . -follow -name SCCS -prune -o -name '*.[chS]' -print )
+endef
+
+.PHONY: cscope
+cscope:
+ $(all_sources) > cscope.files
+ cscope -k -b -q
+
+.PHONY: tags
+tags:
+ $(all_sources) | xargs ctags
+
+.PHONY: TAGS
+TAGS:
+ $(all_sources) | xargs etags
--- /dev/null
+ Minimal OS
+ ----------
+
+This shows some of the stuff that any guest OS will have to set up.
+
+This includes:
+
+ * installing a virtual exception table
+ * handling virtual exceptions
+ * handling asynchronous events
+ * enabling/disabling async events
+ * parsing start_info struct at start-of-day
+ * registering virtual interrupt handlers (for timer interrupts)
+ * a simple page and memory allocator
+ * minimal libc support
+ * minimal Copy-on-Write support
+ * network, block, framebuffer support
+ * transparent access to FileSystem exports (see tools/fs-back)
+
+- to build it just type make.
+
+- to build it with TCP/IP support, download LWIP 1.3.2 source code and type
+
+ make LWIPDIR=/path/to/lwip/source
+
+- to build it with much better libc support, see the stubdom/ directory
+
+- to start it do the following in domain0
+ # xl create -c domain_config
+
+This starts the kernel and prints out a bunch of stuff and then once every
+second the system time.
+
+If you have setup a disk in the config file (e.g.
+disk = [ 'file:/tmp/foo,hda,r' ] ), it will loop reading it. If that disk is
+writable (e.g. disk = [ 'file:/tmp/foo,hda,w' ] ), it will write data patterns
+and re-read them.
+
+If you have setup a network in the config file (e.g. vif = [''] ), it will
+print incoming packets.
+
+If you have setup a VFB in the config file (e.g. vfb = ['type=sdl'] ), it will
+show a mouse with which you can draw color squares.
+
+If you have compiled it with TCP/IP support, it will run a daytime server on
+TCP port 13.
--- /dev/null
+SECTIONS
+{
+ .app.bss : {
+ __app_bss_start = . ;
+ *(.bss .bss.*)
+ *(COMMON)
+ *(.lbss .lbss.*)
+ *(LARGE_COMMON)
+ __app_bss_end = . ;
+ }
+}
--- /dev/null
+@ Offset of the kernel within the RAM. This is a Linux/zImage convention which we
+@ rely on for now.
+#define ZIMAGE_KERNEL_OFFSET 0x8000
+
+.section .text
+
+.globl _start
+_start:
+ @ zImage header
+.rept 8
+ mov r0, r0
+.endr
+ b reset
+ .word 0x016f2818 @ Magic numbers to help the loader
+ .word 0 @ zImage start address (0 = relocatable)
+ .word _edata - _start @ zImage end address (excludes bss section)
+ @ end of zImage header
+
+@ Called at boot time. Sets up MMU, exception vectors and stack, and then calls C arch_init() function.
+@ => r2 -> DTB
+@ <= never returns
+@ Note: this boot code needs to be within the first (1MB - ZIMAGE_KERNEL_OFFSET) of _start.
+reset:
+ @ Problem: the C code wants to be at a known address (_start), but Xen might
+ @ load us anywhere. We initialise the MMU (mapping virtual to physical @ addresses)
+ @ so everything ends up where the code expects it to be.
+ @
+ @ We calculate the offet between where the linker thought _start would be and where
+ @ it actually is and initialise the page tables to have that offset for every page.
+ @
+ @ When we turn on the MMU, we're still executing at the old address. We don't want
+ @ the code to disappear from under us. So we have to do the mapping in stages:
+ @
+ @ 1. set up a mapping to our current page from both its current and desired addresses
+ @ 2. enable the MMU
+ @ 3. jump to the new address
+ @ 4. remap all the other pages with the calculated offset
+
+ adr r1, _start @ r1 = physical address of _start
+ ldr r3, =_start @ r3 = (desired) virtual address of _start
+ sub r9, r1, r3 @ r9 = (physical - virtual) offset
+
+ ldr r7, =_page_dir @ r7 = (desired) virtual addr of translation table
+ add r1, r7, r9 @ r1 = physical addr of translation table
+
+ @ Tell the system where our page table is located.
+ @ This is the 16 KB top-level translation table, in which
+ @ each word maps one 1MB virtual section to a physical section.
+ @ Note: We leave TTBCR as 0, meaning that only TTBR0 is used and
+ @ we use the short-descriptor format (32-bit physical addresses).
+ orr r0, r1, #0b0001011 @ Sharable, Inner/Outer Write-Back Write-Allocate Cacheable
+ mcr p15, 0, r0, c2, c0, 0 @ set TTBR0
+
+ @ Set access permission for domains.
+ @ Domains are deprecated, but we have to configure them anyway.
+ @ We mark every page as being domain 0 and set domain 0 to "client mode"
+ @ (client mode = use access flags in page table).
+ mov r0, #1 @ 1 = client
+ mcr p15, 0, r0, c3, c0, 0 @ DACR
+
+ @ Template (flags) for a 1 MB page-table entry.
+ @ TEX[2:0] C B = 001 1 1 (outer and inner write-back, write-allocate)
+ ldr r8, =(0x2 + /* Section entry */ \
+ 0xc + /* C B */ \
+ (3 << 10) + /* Read/write */ \
+ (1 << 12) + /* TEX */ \
+ (1 << 16) + /* Sharable */ \
+ (1<<19)) /* Non-secure */
+ @ r8 = template page table entry
+
+ @ Add an entry for the current physical section, at the old and new
+ @ addresses. It's OK if they're the same.
+ mov r0, pc, lsr#20
+ mov r0, r0, lsl#20 @ r0 = physical address of this code's section start
+ orr r3, r0, r8 @ r3 = table entry for this section
+ ldr r4, =_start @ r4 = desired virtual address of this section
+ str r3, [r1, r4, lsr#18] @ map desired virtual section to this code
+ str r3, [r1, r0, lsr#18] @ map current section to this code too
+
+ @ Invalidate TLB
+ dsb @ Caching is off, but must still prevent reordering
+ mcr p15, 0, r1, c8, c7, 0 @ TLBIALL
+
+ @ Enable MMU / SCTLR
+ mrc p15, 0, r1, c1, c0, 0 @ SCTLR
+ orr r1, r1, #3 << 11 @ enable icache, branch prediction
+ orr r1, r1, #4 + 1 @ enable dcache, MMU
+ mcr p15, 0, r1, c1, c0, 0 @ SCTLR
+ isb
+
+ ldr r1, =stage2 @ Virtual address of stage2
+ bx r1
+
+@ Called once the MMU is enabled. The boot code and the page table are mapped,
+@ but nothing else is yet.
+@
+@ => r2 -> dtb (physical)
+@ r7 = virtual address of page table
+@ r8 = section entry template (flags)
+@ r9 = desired physical - virtual offset
+@ pc -> somewhere in newly-mapped virtual code section
+stage2:
+ @ Invalidate TLB
+ mcr p15, 0, r1, c8, c7, 0 @ TLBIALL
+ isb
+
+ @ The new mapping has now taken effect:
+ @ r7 -> page_dir
+
+ @ Fill in the whole top-level translation table (at page_dir).
+ @ Populate the whole pagedir with 1MB section descriptors.
+
+ mov r1, r7 @ r1 -> first section entry
+ add r3, r1, #4*4*1024 @ limit (4 GB address space, 4 byte entries)
+ orr r0, r8, r9 @ r0 = entry mapping section zero to start of physical RAM
+1:
+ str r0, [r1],#4 @ write the section entry
+ add r0, r0, #1 << 20 @ next physical page (wraps)
+ cmp r1, r3
+ bne 1b
+
+ @ Invalidate TLB
+ dsb
+ mcr p15, 0, r1, c8, c7, 0 @ TLBIALL
+ isb
+
+ @ Set VBAR -> exception_vector_table
+ @ SCTLR.V = 0
+ adr r0, exception_vector_table
+ mcr p15, 0, r0, c12, c0, 0
+
+ @ Enable hardware floating point:
+ @ 1. Access to CP10 and CP11 must be enabled in the Coprocessor Access
+ @ Control Register (CP15.CACR):
+ mrc p15, 0, r1, c1, c0, 2 @ CACR
+ orr r1, r1, #(3 << 20) + (3 << 22) @ full access for CP10 & CP11
+ mcr p15, 0, r1, c1, c0, 2
+ @ 2. The EN bit in the FPEXC register must be set:
+ vmrs r0, FPEXC
+ orr r0, r0, #1<<30 @ EN (enable)
+ vmsr FPEXC, r0
+
+ @ Initialise 16 KB stack
+ ldr sp, =_boot_stack_end
+
+ sub r0, r2, r9 @ r0 -> device tree (virtual address)
+ mov r1, r9 @ r1 = physical_address_offset
+
+ b arch_init
+
+.pushsection .bss
+@ Note: calling arch_init zeroes out this region.
+.align 12
+.globl shared_info_page
+shared_info_page:
+ .fill (1024), 4, 0x0
+
+.align 3
+.globl irqstack
+.globl irqstack_end
+irqstack:
+ .fill (1024), 4, 0x0
+irqstack_end:
+
+fault_dump:
+ .fill 18, 4, 0x0 @ On fault, we save the registers + CPSR + handler address
+
+.popsection
+
+fault:
+ cpsid aif @ Disable interrupts
+
+ ldr r13, =fault_dump
+ stmia r13, {r0-r12} @ Dump the non-banked registers directly (well, unless from FIQ mode)
+ str r14, [r13, #15 << 2] @ Our r14 is the faulting r15
+ mov r0, r13
+
+ @ Save the caller's CPSR (our SPSR) too.
+ mrs r1, SPSR
+ str r1, [r13, #16 << 2]
+
+ @ Switch to the mode we came from to get r13 and r14.
+ @ If coming from user mode, use System mode instead so we're still
+ @ privileged.
+ and r1, r1, #0x1f @ r1 = SPSR mode
+ cmp r1, #0x10 @ If from User mode
+ moveq r1, #0x1f @ Then use System mode instead
+
+ mrs r3, CPSR @ r3 = our CPSR
+ bic r2, r3, #0x1f
+ orr r2, r2, r1
+ msr CPSR, r2 @ Change to mode r1
+
+ @ Save old mode's r13, r14
+ str r13, [r0, #13 << 2]
+ str r14, [r0, #14 << 2]
+
+ msr CPSR, r3 @ Back to fault mode
+
+ ldr r1, [r0, #17 << 2]
+ sub r1, r1, #12 @ Fix to point at start of handler
+ str r1, [r0, #17 << 2]
+
+ @ Call C code to format the register dump.
+ @ Clobbers the stack, but we're not going to return anyway.
+ ldr sp, =_boot_stack_end
+ bl dump_registers
+ b do_exit
+
+@ We want to store a unique value to identify this handler, without corrupting
+@ any of the registers. So, we store r15 (which will point just after the branch).
+@ Later, we subtract 12 so the user gets pointed at the start of the exception
+@ handler.
+#define FAULT(name) \
+.globl fault_##name; \
+fault_##name: \
+ ldr r13, =fault_dump; \
+ str r15, [r13, #17 << 2]; \
+ b fault
+
+FAULT(reset)
+FAULT(undefined_instruction)
+FAULT(svc)
+FAULT(prefetch_call)
+FAULT(prefetch_abort)
+FAULT(data_abort)
+
+@ exception base address
+.align 5
+.globl exception_vector_table
+@ Note: remember to call CLREX if returning from an exception:
+@ "The architecture enables the local monitor to treat any exclusive store as
+@ matching a previous LDREX address. For this reason, use of the CLREX
+@ instruction to clear an existing tag is required on context switches."
+@ -- ARM Cortex-A Series Programmer’s Guide (Version: 4.0)
+exception_vector_table:
+ b fault_reset
+ b fault_undefined_instruction
+ b fault_svc
+ b fault_prefetch_call
+ b fault_prefetch_abort
+ b fault_data_abort
+ b irq_handler @ IRQ
+ .word 0xe7f000f0 @ abort on FIQ
+
+@ Call fault_undefined_instruction in "Undefined mode"
+bug:
+ .word 0xe7f000f0 @ und/udf - a "Permanently Undefined" instruction
+
+irq_handler:
+ ldr sp, =irqstack_end
+ push {r0 - r12, r14}
+
+ ldr r0, IRQ_handler
+ cmp r0, #0
+ beq bug
+ blx r0 @ call handler
+
+ @ Return from IRQ
+ pop {r0 - r12, r14}
+ clrex
+ subs pc, lr, #4
+
+.globl IRQ_handler
+IRQ_handler:
+ .long 0x0
+
+
+.globl __arch_switch_threads
+@ => r0 = &prev->sp
+@ r1 = &next->sp
+@ <= returns to next thread's saved return address
+__arch_switch_threads:
+ push {r4-r11} @ Store callee-saved registers to old thread's stack
+ stmia r0, {sp, lr} @ Store current sp and ip to prev's struct thread
+
+ ldmia r1, {sp, lr} @ Load new sp, ip from next's struct thread
+ pop {r4-r11} @ Load callee-saved registers from new thread's stack
+
+ bx lr
+
+@ This is called if you try to divide by zero. For now, we make a supervisor call,
+@ which will make us halt.
+.globl raise
+raise:
+ svc 0
+
+.globl arm_start_thread
+arm_start_thread:
+ pop {r0, r1}
+ @ r0 = user data
+ @ r1 -> thread's main function
+ ldr lr, =exit_thread
+ bx r1
--- /dev/null
+#include <mini-os/os.h>
+#include <mini-os/events.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/console.h>
+
+static void virq_debug(evtchn_port_t port, struct pt_regs *regs, void *params)
+{
+ printk("Received a virq_debug event\n");
+}
+
+evtchn_port_t debug_port = -1;
+void arch_init_events(void)
+{
+ debug_port = bind_virq(VIRQ_DEBUG, (evtchn_handler_t)virq_debug, 0);
+ if(debug_port == -1)
+ BUG();
+ unmask_evtchn(debug_port);
+}
+
+void arch_unbind_ports(void)
+{
+ if(debug_port != -1)
+ {
+ mask_evtchn(debug_port);
+ unbind_evtchn(debug_port);
+ }
+}
+
+void arch_fini_events(void)
+{
+}
--- /dev/null
+/******************************************************************************
+ * hypercall.S
+ *
+ * Xen hypercall wrappers
+ *
+ * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <xen/xen.h>
+
+#define __HVC(imm16) .long ((0xE1400070 | (((imm16) & 0xFFF0) << 4) | ((imm16) & 0x000F)) & 0xFFFFFFFF)
+
+#define XEN_IMM 0xEA1
+
+#define HYPERCALL_SIMPLE(hypercall) \
+.globl HYPERVISOR_##hypercall; \
+.align 4,0x90; \
+HYPERVISOR_##hypercall: \
+ mov r12, #__HYPERVISOR_##hypercall; \
+ __HVC(XEN_IMM); \
+ mov pc, lr;
+
+#define _hypercall0 HYPERCALL_SIMPLE
+#define _hypercall1 HYPERCALL_SIMPLE
+#define _hypercall2 HYPERCALL_SIMPLE
+#define _hypercall3 HYPERCALL_SIMPLE
+#define _hypercall4 HYPERCALL_SIMPLE
+
+_hypercall2(sched_op);
+_hypercall2(memory_op);
+_hypercall2(event_channel_op);
+_hypercall2(xen_version);
+_hypercall3(console_io);
+_hypercall1(physdev_op);
+_hypercall3(grant_table_op);
+_hypercall3(vcpu_op);
+_hypercall1(sysctl);
+_hypercall1(domctl);
+_hypercall2(hvm_op);
+_hypercall1(xsm_op);
--- /dev/null
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ /* Note: we currently assume that Xen will load the kernel image
+ * at start-of-RAM + 0x8000. We use this initial 32 KB for the stack
+ * and translation tables.
+ */
+ _boot_stack = 0x400000; /* 16 KB boot stack */
+ _boot_stack_end = 0x404000;
+ _page_dir = 0x404000; /* 16 KB translation table */
+ . = 0x408000;
+ _text = .; /* Text and read-only data */
+ .text : {
+ *(.text)
+ *(.gnu.warning)
+ } = 0x9090
+
+ _etext = .; /* End of text section */
+
+ .rodata : { *(.rodata) *(.rodata.*) }
+ . = ALIGN(4096);
+ _erodata = .;
+
+ /* newlib initialization functions */
+ . = ALIGN(32 / 8);
+ PROVIDE (__preinit_array_start = .);
+ .preinit_array : { *(.preinit_array) }
+ PROVIDE (__preinit_array_end = .);
+ PROVIDE (__init_array_start = .);
+ .init_array : { *(.init_array) }
+ PROVIDE (__init_array_end = .);
+ PROVIDE (__fini_array_start = .);
+ .fini_array : { *(.fini_array) }
+ PROVIDE (__fini_array_end = .);
+
+ .ctors : {
+ __CTOR_LIST__ = .;
+ *(.ctors)
+ CONSTRUCTORS
+ LONG(0)
+ __CTOR_END__ = .;
+ }
+
+ .dtors : {
+ __DTOR_LIST__ = .;
+ *(.dtors)
+ LONG(0)
+ __DTOR_END__ = .;
+ }
+
+ .data : { /* Data */
+ *(.data)
+ }
+
+ /* Note: linker will insert any extra sections here, just before .bss */
+
+ .bss : {
+ _edata = .; /* End of data included in image */
+ /* Nothing after here is included in the zImage's size */
+
+ __bss_start = .;
+ *(.bss)
+ *(.app.bss)
+ }
+ _end = . ;
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.text.exit)
+ *(.data.exit)
+ *(.exitcall.exit)
+ }
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+}
--- /dev/null
+#include <mini-os/console.h>
+#include <xen/memory.h>
+#include <arch_mm.h>
+#include <mini-os/hypervisor.h>
+#include <libfdt.h>
+#include <lib.h>
+
+uint32_t physical_address_offset;
+
+unsigned long allocate_ondemand(unsigned long n, unsigned long alignment)
+{
+ // FIXME
+ BUG();
+}
+
+void arch_init_mm(unsigned long *start_pfn_p, unsigned long *max_pfn_p)
+{
+ int memory;
+ int prop_len = 0;
+ const uint64_t *regs;
+
+ printk(" _text: %p(VA)\n", &_text);
+ printk(" _etext: %p(VA)\n", &_etext);
+ printk(" _erodata: %p(VA)\n", &_erodata);
+ printk(" _edata: %p(VA)\n", &_edata);
+ printk(" stack start: %p(VA)\n", _boot_stack);
+ printk(" _end: %p(VA)\n", &_end);
+
+ if (fdt_num_mem_rsv(device_tree) != 0)
+ printk("WARNING: reserved memory not supported!\n");
+
+ memory = fdt_node_offset_by_prop_value(device_tree, -1, "device_type", "memory", sizeof("memory"));
+ if (memory < 0) {
+ printk("No memory found in FDT!\n");
+ BUG();
+ }
+
+ /* Xen will always provide us at least one bank of memory.
+ * Mini-OS will use the first bank for the time-being. */
+ regs = fdt_getprop(device_tree, memory, "reg", &prop_len);
+
+ /* The property must contain at least the start address
+ * and size, each of which is 8-bytes. */
+ if (regs == NULL || prop_len < 16) {
+ printk("Bad 'reg' property: %p %d\n", regs, prop_len);
+ BUG();
+ }
+
+ unsigned int end = (unsigned int) &_end;
+ paddr_t mem_base = fdt64_to_cpu(regs[0]);
+ uint64_t mem_size = fdt64_to_cpu(regs[1]);
+ printk("Found memory at 0x%llx (len 0x%llx)\n",
+ (unsigned long long) mem_base, (unsigned long long) mem_size);
+
+ BUG_ON(to_virt(mem_base) > (void *) &_text); /* Our image isn't in our RAM! */
+ *start_pfn_p = PFN_UP(to_phys(end));
+ uint64_t heap_len = mem_size - (PFN_PHYS(*start_pfn_p) - mem_base);
+ *max_pfn_p = *start_pfn_p + PFN_DOWN(heap_len);
+
+ printk("Using pages %lu to %lu as free space for heap.\n", *start_pfn_p, *max_pfn_p);
+
+ /* The device tree is probably in memory that we're about to hand over to the page
+ * allocator, so move it to the end and reserve that space.
+ */
+ uint32_t fdt_size = fdt_totalsize(device_tree);
+ void *new_device_tree = to_virt(((*max_pfn_p << PAGE_SHIFT) - fdt_size) & PAGE_MASK);
+ if (new_device_tree != device_tree) {
+ memmove(new_device_tree, device_tree, fdt_size);
+ }
+ device_tree = new_device_tree;
+ *max_pfn_p = to_phys(new_device_tree) >> PAGE_SHIFT;
+}
+
+void arch_init_p2m(unsigned long max_pfn)
+{
+}
+
+void arch_init_demand_mapping_area(unsigned long cur_pfn)
+{
+}
+
+/* Get Xen's suggested physical page assignments for the grant table. */
+static paddr_t get_gnttab_base(void)
+{
+ int hypervisor;
+ int len = 0;
+ const uint64_t *regs;
+ paddr_t gnttab_base;
+
+ hypervisor = fdt_node_offset_by_compatible(device_tree, -1, "xen,xen");
+ BUG_ON(hypervisor < 0);
+
+ regs = fdt_getprop(device_tree, hypervisor, "reg", &len);
+ /* The property contains the address and size, 8-bytes each. */
+ if (regs == NULL || len < 16) {
+ printk("Bad 'reg' property: %p %d\n", regs, len);
+ BUG();
+ }
+
+ gnttab_base = fdt64_to_cpu(regs[0]);
+
+ printk("FDT suggests grant table base %llx\n", (unsigned long long) gnttab_base);
+
+ return gnttab_base;
+}
+
+grant_entry_t *arch_init_gnttab(int nr_grant_frames)
+{
+ struct xen_add_to_physmap xatp;
+ struct gnttab_setup_table setup;
+ xen_pfn_t frames[nr_grant_frames];
+ paddr_t gnttab_table;
+ int i, rc;
+
+ gnttab_table = get_gnttab_base();
+
+ for (i = 0; i < nr_grant_frames; i++)
+ {
+ xatp.domid = DOMID_SELF;
+ xatp.size = 0; /* Seems to be unused */
+ xatp.space = XENMAPSPACE_grant_table;
+ xatp.idx = i;
+ xatp.gpfn = (gnttab_table >> PAGE_SHIFT) + i;
+ rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
+ BUG_ON(rc != 0);
+ }
+
+ setup.dom = DOMID_SELF;
+ setup.nr_frames = nr_grant_frames;
+ set_xen_guest_handle(setup.frame_list, frames);
+ HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+ if (setup.status != 0)
+ {
+ printk("GNTTABOP_setup_table failed; status = %d\n", setup.status);
+ BUG();
+ }
+
+ return to_virt(gnttab_table);
+}
--- /dev/null
+/******************************************************************************
+ * panic.c
+ *
+ * Displays a register dump and stack trace for debugging.
+ *
+ * Copyright (c) 2014, Thomas Leonard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <mini-os/os.h>
+#include <mini-os/console.h>
+#include <arch_mm.h>
+
+extern int irqstack[];
+extern int irqstack_end[];
+
+typedef void handler(void);
+
+extern handler fault_reset;
+extern handler fault_undefined_instruction;
+extern handler fault_svc;
+extern handler fault_prefetch_call;
+extern handler fault_prefetch_abort;
+extern handler fault_data_abort;
+
+void dump_registers(int *saved_registers) {
+ static int in_dump = 0;
+ int *sp, *stack_top, *x;
+ char *fault_name;
+ void *fault_handler;
+ int i;
+
+ if (in_dump)
+ {
+ printk("Crash while in dump_registers! Not generating a second report.\n");
+ return;
+ }
+
+ in_dump = 1;
+
+ fault_handler = (handler *) saved_registers[17];
+ if (fault_handler == fault_reset)
+ fault_name = "reset";
+ else if (fault_handler == fault_undefined_instruction)
+ fault_name = "undefined_instruction";
+ else if (fault_handler == fault_svc)
+ fault_name = "svc";
+ else if (fault_handler == fault_prefetch_call)
+ fault_name = "prefetch_call";
+ else if (fault_handler == fault_prefetch_abort)
+ fault_name = "prefetch_abort";
+ else if (fault_handler == fault_data_abort)
+ fault_name = "data_abort";
+ else
+ fault_name = "unknown fault type!";
+
+ printk("Fault handler at %p called (%s)\n", fault_handler, fault_name);
+
+ for (i = 0; i < 16; i++) {
+ printk("r%d = %x\n", i, saved_registers[i]);
+ }
+ printk("CPSR = %x\n", saved_registers[16]);
+
+ printk("Stack dump (innermost last)\n");
+ sp = (int *) saved_registers[13];
+
+ if (sp >= _boot_stack && sp <= _boot_stack_end)
+ stack_top = _boot_stack_end; /* The boot stack */
+ else if (sp >= irqstack && sp <= irqstack_end)
+ stack_top = irqstack_end; /* The IRQ stack */
+ else
+ stack_top = (int *) ((((unsigned long) sp) | (__STACK_SIZE-1)) + 1); /* A normal thread stack */
+
+ for (x = stack_top - 1; x >= sp; x--)
+ {
+ printk(" [%8p] %8x\n", x, *x);
+ }
+ printk("End of stack\n");
+
+ in_dump = 0;
+}
--- /dev/null
+#include <mini-os/sched.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/console.h>
+
+void arm_start_thread(void);
+
+/* The AAPCS requires the callee (e.g. __arch_switch_threads) to preserve r4-r11. */
+#define CALLEE_SAVED_REGISTERS 8
+
+/* Architecture specific setup of thread creation */
+struct thread* arch_create_thread(char *name, void (*function)(void *),
+ void *data)
+{
+ struct thread *thread;
+
+ thread = xmalloc(struct thread);
+ /* We can't use lazy allocation here since the trap handler runs on the stack */
+ thread->stack = (char *)alloc_pages(STACK_SIZE_PAGE_ORDER);
+ thread->name = name;
+ printk("Thread \"%s\": pointer: 0x%p, stack: 0x%p\n", name, thread,
+ thread->stack);
+
+ /* Save pointer to the thread on the stack, used by current macro */
+ *((unsigned long *)thread->stack) = (unsigned long)thread;
+
+ /* Push the details to pass to arm_start_thread onto the stack. */
+ int *sp = (int *) (thread->stack + STACK_SIZE);
+ *(--sp) = (int) function;
+ *(--sp) = (int) data;
+
+ /* We leave room for the 8 callee-saved registers which we will
+ * try to restore on thread switch, even though they're not needed
+ * for the initial switch. */
+ thread->sp = (unsigned long) sp - 4 * CALLEE_SAVED_REGISTERS;
+
+ thread->ip = (unsigned long) arm_start_thread;
+
+ return thread;
+}
+
+void run_idle_thread(void)
+{
+ __asm__ __volatile__ ("mov sp, %0; bx %1"::
+ "r"(idle_thread->sp + 4 * CALLEE_SAVED_REGISTERS),
+ "r"(idle_thread->ip));
+ /* Never arrive here! */
+}
--- /dev/null
+#include <mini-os/os.h>
+#include <mini-os/kernel.h>
+#include <mini-os/gic.h>
+#include <mini-os/console.h>
+#include <xen/xen.h>
+#include <xen/memory.h>
+#include <xen/hvm/params.h>
+#include <arch_mm.h>
+#include <libfdt.h>
+
+/*
+ * This structure contains start-of-day info, such as pagetable base pointer,
+ * address of the shared_info structure, and things like that.
+ * On x86, the hypervisor passes it to us. On ARM, we fill it in ourselves.
+ */
+union start_info_union start_info_union;
+
+/*
+ * Shared page for communicating with the hypervisor.
+ * Events flags go here, for example.
+ */
+shared_info_t *HYPERVISOR_shared_info;
+
+extern char shared_info_page[PAGE_SIZE];
+
+void *device_tree;
+
+static int hvm_get_parameter(int idx, uint64_t *value)
+{
+ struct xen_hvm_param xhv;
+ int ret;
+
+ xhv.domid = DOMID_SELF;
+ xhv.index = idx;
+ ret = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
+ if (ret < 0) {
+ BUG();
+ }
+ *value = xhv.value;
+ return ret;
+}
+
+static void get_console(void)
+{
+ uint64_t v = -1;
+
+ hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
+ start_info.console.domU.evtchn = v;
+
+ hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v);
+ start_info.console.domU.mfn = v;
+
+ printk("Console is on port %d\n", start_info.console.domU.evtchn);
+ printk("Console ring is at mfn %lx\n", (unsigned long) start_info.console.domU.mfn);
+}
+
+void get_xenbus(void)
+{
+ uint64_t value;
+
+ if (hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &value))
+ BUG();
+
+ start_info.store_evtchn = (int)value;
+
+ if(hvm_get_parameter(HVM_PARAM_STORE_PFN, &value))
+ BUG();
+ start_info.store_mfn = (unsigned long)value;
+}
+
+/*
+ * INITIAL C ENTRY POINT.
+ */
+void arch_init(void *dtb_pointer, uint32_t physical_offset)
+{
+ struct xen_add_to_physmap xatp;
+ int r;
+
+ memset(&__bss_start, 0, &_end - &__bss_start);
+
+ physical_address_offset = physical_offset;
+
+ xprintk("Virtual -> physical offset = %x\n", physical_address_offset);
+
+ xprintk("Checking DTB at %p...\n", dtb_pointer);
+
+ if ((r = fdt_check_header(dtb_pointer))) {
+ xprintk("Invalid DTB from Xen: %s\n", fdt_strerror(r));
+ BUG();
+ }
+ device_tree = dtb_pointer;
+
+ /* Map shared_info page */
+ xatp.domid = DOMID_SELF;
+ xatp.idx = 0;
+ xatp.space = XENMAPSPACE_shared_info;
+ xatp.gpfn = virt_to_pfn(shared_info_page);
+ if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0)
+ BUG();
+ HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
+
+ /* Fill in start_info */
+ get_console();
+ get_xenbus();
+
+ gic_init();
+
+ start_kernel();
+}
+
+void
+arch_fini(void)
+{
+}
+
+void
+arch_do_exit(void)
+{
+}
--- /dev/null
+#include <mini-os/os.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/events.h>
+#include <mini-os/traps.h>
+#include <mini-os/types.h>
+#include <mini-os/time.h>
+#include <mini-os/lib.h>
+
+//#define VTIMER_DEBUG
+#ifdef VTIMER_DEBUG
+#define DEBUG(_f, _a...) \
+ printk("MINI_OS(file=vtimer.c, line=%d) " _f , __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...) ((void)0)
+#endif
+
+/************************************************************************
+ * Time functions
+ *************************************************************************/
+
+static uint64_t cntvct_at_init;
+static uint32_t counter_freq;
+
+/* Compute with 96 bit intermediate result: (a*b)/c */
+uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+{
+ union {
+ uint64_t ll;
+ struct {
+ uint32_t low, high;
+ } l;
+ } u, res;
+ uint64_t rl, rh;
+
+ u.ll = a;
+ rl = (uint64_t)u.l.low * (uint64_t)b;
+ rh = (uint64_t)u.l.high * (uint64_t)b;
+ rh += (rl >> 32);
+ res.l.high = rh / c;
+ res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
+ return res.ll;
+}
+
+static inline s_time_t ticks_to_ns(uint64_t ticks)
+{
+ return muldiv64(ticks, SECONDS(1), counter_freq);
+}
+
+static inline uint64_t ns_to_ticks(s_time_t ns)
+{
+ return muldiv64(ns, counter_freq, SECONDS(1));
+}
+
+/* Wall-clock time is not currently available on ARM, so this is always zero for now:
+ * http://wiki.xenproject.org/wiki/Xen_ARM_TODO#Expose_Wallclock_time_to_guests
+ */
+static struct timespec shadow_ts;
+
+static inline uint64_t read_virtual_count(void)
+{
+ uint32_t c_lo, c_hi;
+ __asm__ __volatile__("mrrc p15, 1, %0, %1, c14":"=r"(c_lo), "=r"(c_hi));
+ return (((uint64_t) c_hi) << 32) + c_lo;
+}
+
+/* monotonic_clock(): returns # of nanoseconds passed since time_init()
+ * Note: This function is required to return accurate
+ * time even in the absence of multiple timer ticks.
+ */
+uint64_t monotonic_clock(void)
+{
+ return ticks_to_ns(read_virtual_count() - cntvct_at_init);
+}
+
+int gettimeofday(struct timeval *tv, void *tz)
+{
+ uint64_t nsec = monotonic_clock();
+ nsec += shadow_ts.tv_nsec;
+
+ tv->tv_sec = shadow_ts.tv_sec;
+ tv->tv_sec += NSEC_TO_SEC(nsec);
+ tv->tv_usec = NSEC_TO_USEC(nsec % 1000000000UL);
+
+ return 0;
+}
+
+/* Set the timer and mask. */
+void write_timer_ctl(uint32_t value) {
+ __asm__ __volatile__(
+ "mcr p15, 0, %0, c14, c3, 1\n"
+ "isb"::"r"(value));
+}
+
+void set_vtimer_compare(uint64_t value) {
+ DEBUG("New CompareValue : %llx\n", value);
+
+ __asm__ __volatile__("mcrr p15, 3, %0, %H0, c14"
+ ::"r"(value));
+
+ /* Enable timer and unmask the output signal */
+ write_timer_ctl(1);
+}
+
+void unset_vtimer_compare(void) {
+ /* Disable timer and mask the output signal */
+ write_timer_ctl(2);
+}
+
+void block_domain(s_time_t until)
+{
+ uint64_t until_count = ns_to_ticks(until) + cntvct_at_init;
+ ASSERT(irqs_disabled());
+ if (read_virtual_count() < until_count)
+ {
+ set_vtimer_compare(until_count);
+ __asm__ __volatile__("wfi");
+ unset_vtimer_compare();
+
+ /* Give the IRQ handler a chance to handle whatever woke us up. */
+ local_irq_enable();
+ local_irq_disable();
+ }
+}
+
+void init_time(void)
+{
+ printk("Initialising timer interface\n");
+
+ __asm__ __volatile__("mrc p15, 0, %0, c14, c0, 0":"=r"(counter_freq));
+ cntvct_at_init = read_virtual_count();
+ printk("Virtual Count register is %llx, freq = %d Hz\n", cntvct_at_init, counter_freq);
+}
+
+void fini_time(void)
+{
+}
--- /dev/null
+#
+# x86 architecture specific makefiles.
+# It's is used for x86_32, x86_32y and x86_64
+#
+
+TOPLEVEL_DIR = $(CURDIR)/../..
+include ../../Config.mk
+
+# include arch.mk has to be before mini-os.mk!
+
+include arch.mk
+include ../../minios.mk
+
+# Sources here are all *.c *.S without $(MINIOS_TARGET_ARCH).S
+# This is handled in $(HEAD_ARCH_OBJ)
+ARCH_SRCS := $(wildcard *.c)
+
+# The objects built from the sources.
+ARCH_OBJS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(ARCH_SRCS))
+
+all: $(OBJ_DIR)/$(ARCH_LIB)
+
+# $(HEAD_ARCH_OBJ) is only build here, needed on linking
+# in ../../Makefile.
+$(OBJ_DIR)/$(ARCH_LIB): $(ARCH_OBJS) $(OBJ_DIR)/$(HEAD_ARCH_OBJ)
+ $(AR) rv $(OBJ_DIR)/$(ARCH_LIB) $(ARCH_OBJS)
+
+clean:
+ rm -f $(OBJ_DIR)/$(ARCH_LIB) $(ARCH_OBJS) $(OBJ_DIR)/$(HEAD_ARCH_OBJ)
+
--- /dev/null
+#
+# Architecture special makerules for x86 family
+# (including x86_32, x86_32y and x86_64).
+#
+
+ifeq ($(MINIOS_TARGET_ARCH),x86_32)
+ARCH_CFLAGS := -m32 -march=i686
+ARCH_LDFLAGS := -m elf_i386
+ARCH_ASFLAGS := -m32
+EXTRA_INC += $(TARGET_ARCH_FAM)/$(MINIOS_TARGET_ARCH)
+EXTRA_SRC += arch/$(EXTRA_INC)
+endif
+
+ifeq ($(MINIOS_TARGET_ARCH),x86_64)
+ARCH_CFLAGS := -m64 -mno-red-zone -fno-reorder-blocks
+ARCH_CFLAGS += -fno-asynchronous-unwind-tables
+ARCH_ASFLAGS := -m64
+ARCH_LDFLAGS := -m elf_x86_64
+EXTRA_INC += $(TARGET_ARCH_FAM)/$(MINIOS_TARGET_ARCH)
+EXTRA_SRC += arch/$(EXTRA_INC)
+endif
+
--- /dev/null
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <mini-os/events.h>
+
+#if defined(__x86_64__)
+char irqstack[2 * STACK_SIZE];
+
+static struct pda
+{
+ int irqcount; /* offset 0 (used in x86_64.S) */
+ char *irqstackptr; /* 8 */
+} cpu0_pda;
+#endif
+
+void arch_init_events(void)
+{
+#if defined(__x86_64__)
+ asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
+ wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
+ cpu0_pda.irqcount = -1;
+ cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE)
+ & ~(STACK_SIZE - 1));
+#endif
+}
+
+void arch_unbind_ports(void)
+{
+}
+
+void arch_fini_events(void)
+{
+#if defined(__x86_64__)
+ wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */
+#endif
+}
--- /dev/null
+/*
+ * Copyright (C) 2009, Netronome Systems, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include <mini-os/types.h>
+#include <mini-os/lib.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/mm.h>
+#include <mini-os/ioremap.h>
+
+/* Map a physical address range into virtual address space with provided
+ * flags. Return a virtual address range it is mapped to. */
+static void *__do_ioremap(unsigned long phys_addr, unsigned long size,
+ unsigned long prot)
+{
+ unsigned long va;
+ unsigned long mfns, mfn;
+ unsigned long num_pages, offset;
+
+ /* allow non page aligned addresses but for mapping we need to align them */
+ offset = (phys_addr & ~PAGE_MASK);
+ num_pages = (offset + size + PAGE_SIZE - 1) / PAGE_SIZE;
+ phys_addr &= PAGE_MASK;
+ mfns = mfn = phys_addr >> PAGE_SHIFT;
+
+ va = (unsigned long)map_frames_ex(&mfns, num_pages, 0, 1, 1,
+ DOMID_IO, NULL, prot);
+ return (void *)(va + offset);
+}
+
+void *ioremap(unsigned long phys_addr, unsigned long size)
+{
+ return __do_ioremap(phys_addr, size, IO_PROT);
+}
+
+void *ioremap_nocache(unsigned long phys_addr, unsigned long size)
+{
+ return __do_ioremap(phys_addr, size, IO_PROT_NOCACHE);
+}
+
+/* Un-map the io-remapped region. Currently no list of existing mappings is
+ * maintained, so the caller has to supply the size */
+void iounmap(void *virt_addr, unsigned long size)
+{
+ unsigned long num_pages;
+ unsigned long va = (unsigned long)virt_addr;
+
+ /* work out number of frames to unmap */
+ num_pages = ((va & ~PAGE_MASK) + size + PAGE_SIZE - 1) / PAGE_SIZE;
+
+ unmap_frames(va & PAGE_MASK, num_pages);
+}
+
+
+
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 indent-tabs-mode:nil -*- */
--- /dev/null
+#include <mini-os/iorw.h>
+
+void iowrite8(volatile void* addr, uint8_t val)
+{
+ *((volatile uint8_t*)addr) = val;
+}
+void iowrite16(volatile void* addr, uint16_t val)
+{
+ *((volatile uint16_t*)addr) = val;
+}
+void iowrite32(volatile void* addr, uint32_t val)
+{
+ *((volatile uint32_t*)addr) = val;
+}
+void iowrite64(volatile void* addr, uint64_t val)
+{
+ *((volatile uint64_t*)addr) = val;
+}
+
+uint8_t ioread8(volatile void* addr)
+{
+ return *((volatile uint8_t*) addr);
+}
+uint16_t ioread16(volatile void* addr)
+{
+ return *((volatile uint16_t*) addr);
+}
+uint32_t ioread32(volatile void* addr)
+{
+ return *((volatile uint32_t*) addr);
+}
+uint64_t ioread64(volatile void* addr)
+{
+ return *((volatile uint64_t*) addr);
+}
--- /dev/null
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x0;
+ _text = .; /* Text and read-only data */
+ .text : {
+ *(.text)
+ *(.gnu.warning)
+ } = 0x9090
+
+ _etext = .; /* End of text section */
+
+ .rodata : { *(.rodata) *(.rodata.*) }
+ . = ALIGN(4096);
+ _erodata = .;
+
+ /* newlib initialization functions */
+ . = ALIGN(32 / 8);
+ PROVIDE (__preinit_array_start = .);
+ .preinit_array : { *(.preinit_array) }
+ PROVIDE (__preinit_array_end = .);
+ PROVIDE (__init_array_start = .);
+ .init_array : { *(.init_array) }
+ PROVIDE (__init_array_end = .);
+ PROVIDE (__fini_array_start = .);
+ .fini_array : { *(.fini_array) }
+ PROVIDE (__fini_array_end = .);
+
+ .ctors : {
+ __CTOR_LIST__ = .;
+ *(.ctors)
+ CONSTRUCTORS
+ LONG(0)
+ __CTOR_END__ = .;
+ }
+
+ .dtors : {
+ __DTOR_LIST__ = .;
+ *(.dtors)
+ LONG(0)
+ __DTOR_END__ = .;
+ }
+
+ .data : { /* Data */
+ *(.data)
+ }
+
+ _edata = .; /* End of data section */
+
+ __bss_start = .; /* BSS */
+ .bss : {
+ *(.bss)
+ *(.app.bss)
+ }
+ _end = . ;
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.text.exit)
+ *(.data.exit)
+ *(.exitcall.exit)
+ }
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+}
--- /dev/null
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x0;
+ _text = .; /* Text and read-only data */
+ .text : {
+ *(.text)
+ *(.gnu.warning)
+ } = 0x9090
+
+ _etext = .; /* End of text section */
+
+ .rodata : { *(.rodata) *(.rodata.*) }
+ . = ALIGN(4096);
+ _erodata = .;
+
+ /* newlib initialization functions */
+ . = ALIGN(64 / 8);
+ PROVIDE (__preinit_array_start = .);
+ .preinit_array : { *(.preinit_array) }
+ PROVIDE (__preinit_array_end = .);
+ PROVIDE (__init_array_start = .);
+ .init_array : { *(.init_array) }
+ PROVIDE (__init_array_end = .);
+ PROVIDE (__fini_array_start = .);
+ .fini_array : { *(.fini_array) }
+ PROVIDE (__fini_array_end = .);
+
+ .ctors : {
+ __CTOR_LIST__ = .;
+ *(.ctors)
+ CONSTRUCTORS
+ QUAD(0)
+ __CTOR_END__ = .;
+ }
+
+ .dtors : {
+ __DTOR_LIST__ = .;
+ *(.dtors)
+ QUAD(0)
+ __DTOR_END__ = .;
+ }
+
+ .data : { /* Data */
+ *(.data)
+ }
+
+ _edata = .; /* End of data section */
+
+ __bss_start = .; /* BSS */
+ .bss : {
+ *(.bss)
+ *(.app.bss)
+ }
+ _end = . ;
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.text.exit)
+ *(.data.exit)
+ *(.exitcall.exit)
+ }
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+}
--- /dev/null
+/*
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: mm.c
+ * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
+ * Changes: Grzegorz Milos
+ *
+ * Date: Aug 2003, chages Aug 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: memory management related functions
+ * contains buddy page allocator from Xen.
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <mini-os/os.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/mm.h>
+#include <mini-os/types.h>
+#include <mini-os/lib.h>
+#include <mini-os/xmalloc.h>
+#include <xen/memory.h>
+
+#ifdef MM_DEBUG
+#define DEBUG(_f, _a...) \
+ printk("MINI_OS(file=mm.c, line=%d) " _f "\n", __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...) ((void)0)
+#endif
+
+unsigned long *phys_to_machine_mapping;
+unsigned long mfn_zero;
+extern char stack[];
+extern void page_walk(unsigned long va);
+
+/*
+ * Make pt_pfn a new 'level' page table frame and hook it into the page
+ * table at offset in previous level MFN (pref_l_mfn). pt_pfn is a guest
+ * PFN.
+ */
+static void new_pt_frame(unsigned long *pt_pfn, unsigned long prev_l_mfn,
+ unsigned long offset, unsigned long level)
+{
+ pgentry_t *tab = (pgentry_t *)start_info.pt_base;
+ unsigned long pt_page = (unsigned long)pfn_to_virt(*pt_pfn);
+ pgentry_t prot_e, prot_t;
+ mmu_update_t mmu_updates[1];
+ int rc;
+
+ prot_e = prot_t = 0;
+ DEBUG("Allocating new L%d pt frame for pfn=%lx, "
+ "prev_l_mfn=%lx, offset=%lx",
+ level, *pt_pfn, prev_l_mfn, offset);
+
+ /* We need to clear the page, otherwise we might fail to map it
+ as a page table page */
+ memset((void*) pt_page, 0, PAGE_SIZE);
+
+ switch ( level )
+ {
+ case L1_FRAME:
+ prot_e = L1_PROT;
+ prot_t = L2_PROT;
+ break;
+ case L2_FRAME:
+ prot_e = L2_PROT;
+ prot_t = L3_PROT;
+ break;
+#if defined(__x86_64__)
+ case L3_FRAME:
+ prot_e = L3_PROT;
+ prot_t = L4_PROT;
+ break;
+#endif
+ default:
+ printk("new_pt_frame() called with invalid level number %d\n", level);
+ do_exit();
+ break;
+ }
+
+ /* Make PFN a page table page */
+#if defined(__x86_64__)
+ tab = pte_to_virt(tab[l4_table_offset(pt_page)]);
+#endif
+ tab = pte_to_virt(tab[l3_table_offset(pt_page)]);
+
+ mmu_updates[0].ptr = (tab[l2_table_offset(pt_page)] & PAGE_MASK) +
+ sizeof(pgentry_t) * l1_table_offset(pt_page);
+ mmu_updates[0].val = (pgentry_t)pfn_to_mfn(*pt_pfn) << PAGE_SHIFT |
+ (prot_e & ~_PAGE_RW);
+
+ if ( (rc = HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF)) < 0 )
+ {
+ printk("ERROR: PTE for new page table page could not be updated\n");
+ printk(" mmu_update failed with rc=%d\n", rc);
+ do_exit();
+ }
+
+ /* Hook the new page table page into the hierarchy */
+ mmu_updates[0].ptr =
+ ((pgentry_t)prev_l_mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
+ mmu_updates[0].val = (pgentry_t)pfn_to_mfn(*pt_pfn) << PAGE_SHIFT | prot_t;
+
+ if ( (rc = HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF)) < 0 )
+ {
+ printk("ERROR: mmu_update failed with rc=%d\n", rc);
+ do_exit();
+ }
+
+ *pt_pfn += 1;
+}
+
+/*
+ * Checks if a pagetable frame is needed at 'level' to map a given
+ * address. Note, this function is specific to the initial page table
+ * building.
+ */
+static int need_pt_frame(unsigned long va, int level)
+{
+ unsigned long hyp_virt_start = HYPERVISOR_VIRT_START;
+#if defined(__x86_64__)
+ unsigned long hyp_virt_end = HYPERVISOR_VIRT_END;
+#else
+ unsigned long hyp_virt_end = 0xffffffff;
+#endif
+
+ /* In general frames will _not_ be needed if they were already
+ allocated to map the hypervisor into our VA space */
+#if defined(__x86_64__)
+ if ( level == L3_FRAME )
+ {
+ if ( l4_table_offset(va) >=
+ l4_table_offset(hyp_virt_start) &&
+ l4_table_offset(va) <=
+ l4_table_offset(hyp_virt_end))
+ return 0;
+ return 1;
+ }
+ else
+#endif
+
+ if ( level == L2_FRAME )
+ {
+#if defined(__x86_64__)
+ if ( l4_table_offset(va) >=
+ l4_table_offset(hyp_virt_start) &&
+ l4_table_offset(va) <=
+ l4_table_offset(hyp_virt_end))
+#endif
+ if ( l3_table_offset(va) >=
+ l3_table_offset(hyp_virt_start) &&
+ l3_table_offset(va) <=
+ l3_table_offset(hyp_virt_end))
+ return 0;
+
+ return 1;
+ }
+ else
+ /* Always need l1 frames */
+ if ( level == L1_FRAME )
+ return 1;
+
+ printk("ERROR: Unknown frame level %d, hypervisor %llx,%llx\n",
+ level, hyp_virt_start, hyp_virt_end);
+ return -1;
+}
+
+/*
+ * Build the initial pagetable.
+ */
+static void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
+{
+ unsigned long start_address, end_address;
+ unsigned long pfn_to_map, pt_pfn = *start_pfn;
+ static mmu_update_t mmu_updates[L1_PAGETABLE_ENTRIES + 1];
+ pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
+ unsigned long pt_mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
+ unsigned long offset;
+ int count = 0;
+ int rc;
+
+ pfn_to_map =
+ (start_info.nr_pt_frames - NOT_L1_FRAMES) * L1_PAGETABLE_ENTRIES;
+
+ if ( *max_pfn >= virt_to_pfn(HYPERVISOR_VIRT_START) )
+ {
+ printk("WARNING: Mini-OS trying to use Xen virtual space. "
+ "Truncating memory from %dMB to ",
+ ((unsigned long)pfn_to_virt(*max_pfn) -
+ (unsigned long)&_text)>>20);
+ *max_pfn = virt_to_pfn(HYPERVISOR_VIRT_START - PAGE_SIZE);
+ printk("%dMB\n",
+ ((unsigned long)pfn_to_virt(*max_pfn) -
+ (unsigned long)&_text)>>20);
+ }
+
+ start_address = (unsigned long)pfn_to_virt(pfn_to_map);
+ end_address = (unsigned long)pfn_to_virt(*max_pfn);
+
+ /* We worked out the virtual memory range to map, now mapping loop */
+ printk("Mapping memory range 0x%lx - 0x%lx\n", start_address, end_address);
+
+ while ( start_address < end_address )
+ {
+ tab = (pgentry_t *)start_info.pt_base;
+ pt_mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
+
+#if defined(__x86_64__)
+ offset = l4_table_offset(start_address);
+ /* Need new L3 pt frame */
+ if ( !(start_address & L3_MASK) )
+ if ( need_pt_frame(start_address, L3_FRAME) )
+ new_pt_frame(&pt_pfn, pt_mfn, offset, L3_FRAME);
+
+ page = tab[offset];
+ pt_mfn = pte_to_mfn(page);
+ tab = to_virt(mfn_to_pfn(pt_mfn) << PAGE_SHIFT);
+#endif
+ offset = l3_table_offset(start_address);
+ /* Need new L2 pt frame */
+ if ( !(start_address & L2_MASK) )
+ if ( need_pt_frame(start_address, L2_FRAME) )
+ new_pt_frame(&pt_pfn, pt_mfn, offset, L2_FRAME);
+
+ page = tab[offset];
+ pt_mfn = pte_to_mfn(page);
+ tab = to_virt(mfn_to_pfn(pt_mfn) << PAGE_SHIFT);
+ offset = l2_table_offset(start_address);
+ /* Need new L1 pt frame */
+ if ( !(start_address & L1_MASK) )
+ if ( need_pt_frame(start_address, L1_FRAME) )
+ new_pt_frame(&pt_pfn, pt_mfn, offset, L1_FRAME);
+
+ page = tab[offset];
+ pt_mfn = pte_to_mfn(page);
+ offset = l1_table_offset(start_address);
+
+ mmu_updates[count].ptr =
+ ((pgentry_t)pt_mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
+ mmu_updates[count].val =
+ (pgentry_t)pfn_to_mfn(pfn_to_map++) << PAGE_SHIFT | L1_PROT;
+ count++;
+ if ( count == L1_PAGETABLE_ENTRIES || pfn_to_map == *max_pfn )
+ {
+ rc = HYPERVISOR_mmu_update(mmu_updates, count, NULL, DOMID_SELF);
+ if ( rc < 0 )
+ {
+ printk("ERROR: build_pagetable(): PTE could not be updated\n");
+ printk(" mmu_update failed with rc=%d\n", rc);
+ do_exit();
+ }
+ count = 0;
+ }
+ start_address += PAGE_SIZE;
+ }
+
+ *start_pfn = pt_pfn;
+}
+
+/*
+ * Mark portion of the address space read only.
+ */
+extern struct shared_info shared_info;
+static void set_readonly(void *text, void *etext)
+{
+ unsigned long start_address =
+ ((unsigned long) text + PAGE_SIZE - 1) & PAGE_MASK;
+ unsigned long end_address = (unsigned long) etext;
+ static mmu_update_t mmu_updates[L1_PAGETABLE_ENTRIES + 1];
+ pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
+ unsigned long mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
+ unsigned long offset;
+ int count = 0;
+ int rc;
+
+ printk("setting %p-%p readonly\n", text, etext);
+
+ while ( start_address + PAGE_SIZE <= end_address )
+ {
+ tab = (pgentry_t *)start_info.pt_base;
+ mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
+
+#if defined(__x86_64__)
+ offset = l4_table_offset(start_address);
+ page = tab[offset];
+ mfn = pte_to_mfn(page);
+ tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
+#endif
+ offset = l3_table_offset(start_address);
+ page = tab[offset];
+ mfn = pte_to_mfn(page);
+ tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
+ offset = l2_table_offset(start_address);
+ page = tab[offset];
+ mfn = pte_to_mfn(page);
+ tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
+
+ offset = l1_table_offset(start_address);
+
+ if ( start_address != (unsigned long)&shared_info )
+ {
+ mmu_updates[count].ptr =
+ ((pgentry_t)mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
+ mmu_updates[count].val = tab[offset] & ~_PAGE_RW;
+ count++;
+ }
+ else
+ printk("skipped %p\n", start_address);
+
+ start_address += PAGE_SIZE;
+
+ if ( count == L1_PAGETABLE_ENTRIES ||
+ start_address + PAGE_SIZE > end_address )
+ {
+ rc = HYPERVISOR_mmu_update(mmu_updates, count, NULL, DOMID_SELF);
+ if ( rc < 0 )
+ {
+ printk("ERROR: set_readonly(): PTE could not be updated\n");
+ do_exit();
+ }
+ count = 0;
+ }
+ }
+
+ {
+ mmuext_op_t op = {
+ .cmd = MMUEXT_TLB_FLUSH_ALL,
+ };
+ int count;
+ HYPERVISOR_mmuext_op(&op, 1, &count, DOMID_SELF);
+ }
+}
+
+/*
+ * A useful mem testing function. Write the address to every address in the
+ * range provided and read back the value. If verbose, print page walk to
+ * some VA
+ *
+ * If we get MEM_TEST_MAX_ERRORS we might as well stop
+ */
+#define MEM_TEST_MAX_ERRORS 10
+int mem_test(unsigned long *start_va, unsigned long *end_va, int verbose)
+{
+ unsigned long mask = 0x10000;
+ unsigned long *pointer;
+ int error_count = 0;
+
+ /* write values and print page walks */
+ if ( verbose && (((unsigned long)start_va) & 0xfffff) )
+ {
+ printk("MemTest Start: 0x%lx\n", start_va);
+ page_walk((unsigned long)start_va);
+ }
+ for ( pointer = start_va; pointer < end_va; pointer++ )
+ {
+ if ( verbose && !(((unsigned long)pointer) & 0xfffff) )
+ {
+ printk("Writing to %lx\n", pointer);
+ page_walk((unsigned long)pointer);
+ }
+ *pointer = (unsigned long)pointer & ~mask;
+ }
+ if ( verbose && (((unsigned long)end_va) & 0xfffff) )
+ {
+ printk("MemTest End: %lx\n", end_va-1);
+ page_walk((unsigned long)end_va-1);
+ }
+
+ /* verify values */
+ for ( pointer = start_va; pointer < end_va; pointer++ )
+ {
+ if ( ((unsigned long)pointer & ~mask) != *pointer )
+ {
+ printk("Read error at 0x%lx. Read: 0x%lx, should read 0x%lx\n",
+ (unsigned long)pointer, *pointer,
+ ((unsigned long)pointer & ~mask));
+ error_count++;
+ if ( error_count >= MEM_TEST_MAX_ERRORS )
+ {
+ printk("mem_test: too many errors\n");
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*
+ * get the PTE for virtual address va if it exists. Otherwise NULL.
+ */
+static pgentry_t *get_pgt(unsigned long va)
+{
+ unsigned long mfn;
+ pgentry_t *tab;
+ unsigned offset;
+
+ tab = (pgentry_t *)start_info.pt_base;
+ mfn = virt_to_mfn(start_info.pt_base);
+
+#if defined(__x86_64__)
+ offset = l4_table_offset(va);
+ if ( !(tab[offset] & _PAGE_PRESENT) )
+ return NULL;
+ mfn = pte_to_mfn(tab[offset]);
+ tab = mfn_to_virt(mfn);
+#endif
+ offset = l3_table_offset(va);
+ if ( !(tab[offset] & _PAGE_PRESENT) )
+ return NULL;
+ mfn = pte_to_mfn(tab[offset]);
+ tab = mfn_to_virt(mfn);
+ offset = l2_table_offset(va);
+ if ( !(tab[offset] & _PAGE_PRESENT) )
+ return NULL;
+ mfn = pte_to_mfn(tab[offset]);
+ tab = mfn_to_virt(mfn);
+ offset = l1_table_offset(va);
+ return &tab[offset];
+}
+
+
+/*
+ * return a valid PTE for a given virtual address. If PTE does not exist,
+ * allocate page-table pages.
+ */
+pgentry_t *need_pgt(unsigned long va)
+{
+ unsigned long pt_mfn;
+ pgentry_t *tab;
+ unsigned long pt_pfn;
+ unsigned offset;
+
+ tab = (pgentry_t *)start_info.pt_base;
+ pt_mfn = virt_to_mfn(start_info.pt_base);
+
+#if defined(__x86_64__)
+ offset = l4_table_offset(va);
+ if ( !(tab[offset] & _PAGE_PRESENT) )
+ {
+ pt_pfn = virt_to_pfn(alloc_page());
+ new_pt_frame(&pt_pfn, pt_mfn, offset, L3_FRAME);
+ }
+ ASSERT(tab[offset] & _PAGE_PRESENT);
+ pt_mfn = pte_to_mfn(tab[offset]);
+ tab = mfn_to_virt(pt_mfn);
+#endif
+ offset = l3_table_offset(va);
+ if ( !(tab[offset] & _PAGE_PRESENT) )
+ {
+ pt_pfn = virt_to_pfn(alloc_page());
+ new_pt_frame(&pt_pfn, pt_mfn, offset, L2_FRAME);
+ }
+ ASSERT(tab[offset] & _PAGE_PRESENT);
+ pt_mfn = pte_to_mfn(tab[offset]);
+ tab = mfn_to_virt(pt_mfn);
+ offset = l2_table_offset(va);
+ if ( !(tab[offset] & _PAGE_PRESENT) )
+ {
+ pt_pfn = virt_to_pfn(alloc_page());
+ new_pt_frame(&pt_pfn, pt_mfn, offset, L1_FRAME);
+ }
+ ASSERT(tab[offset] & _PAGE_PRESENT);
+ pt_mfn = pte_to_mfn(tab[offset]);
+ tab = mfn_to_virt(pt_mfn);
+
+ offset = l1_table_offset(va);
+ return &tab[offset];
+}
+
+/*
+ * Reserve an area of virtual address space for mappings and Heap
+ */
+static unsigned long demand_map_area_start;
+#ifdef __x86_64__
+#define DEMAND_MAP_PAGES ((128ULL << 30) / PAGE_SIZE)
+#else
+#define DEMAND_MAP_PAGES ((2ULL << 30) / PAGE_SIZE)
+#endif
+
+#ifndef HAVE_LIBC
+#define HEAP_PAGES 0
+#else
+unsigned long heap, brk, heap_mapped, heap_end;
+#ifdef __x86_64__
+#define HEAP_PAGES ((128ULL << 30) / PAGE_SIZE)
+#else
+#define HEAP_PAGES ((1ULL << 30) / PAGE_SIZE)
+#endif
+#endif
+
+void arch_init_demand_mapping_area(unsigned long cur_pfn)
+{
+ cur_pfn++;
+
+ demand_map_area_start = (unsigned long) pfn_to_virt(cur_pfn);
+ cur_pfn += DEMAND_MAP_PAGES;
+ printk("Demand map pfns at %lx-%lx.\n",
+ demand_map_area_start, pfn_to_virt(cur_pfn));
+
+#ifdef HAVE_LIBC
+ cur_pfn++;
+ heap_mapped = brk = heap = (unsigned long) pfn_to_virt(cur_pfn);
+ cur_pfn += HEAP_PAGES;
+ heap_end = (unsigned long) pfn_to_virt(cur_pfn);
+ printk("Heap resides at %lx-%lx.\n", brk, heap_end);
+#endif
+}
+
+unsigned long allocate_ondemand(unsigned long n, unsigned long alignment)
+{
+ unsigned long x;
+ unsigned long y = 0;
+
+ /* Find a properly aligned run of n contiguous frames */
+ for ( x = 0;
+ x <= DEMAND_MAP_PAGES - n;
+ x = (x + y + 1 + alignment - 1) & ~(alignment - 1) )
+ {
+ unsigned long addr = demand_map_area_start + x * PAGE_SIZE;
+ pgentry_t *pgt = get_pgt(addr);
+ for ( y = 0; y < n; y++, addr += PAGE_SIZE )
+ {
+ if ( !(addr & L1_MASK) )
+ pgt = get_pgt(addr);
+ if ( pgt )
+ {
+ if ( *pgt & _PAGE_PRESENT )
+ break;
+ pgt++;
+ }
+ }
+ if ( y == n )
+ break;
+ }
+ if ( y != n )
+ {
+ printk("Failed to find %ld frames!\n", n);
+ return 0;
+ }
+ return demand_map_area_start + x * PAGE_SIZE;
+}
+
+/*
+ * Map an array of MFNs contiguously into virtual address space starting at
+ * va. map f[i*stride]+i*increment for i in 0..n-1.
+ */
+#define MAP_BATCH ((STACK_SIZE / 2) / sizeof(mmu_update_t))
+void do_map_frames(unsigned long va,
+ const unsigned long *mfns, unsigned long n,
+ unsigned long stride, unsigned long incr,
+ domid_t id, int *err, unsigned long prot)
+{
+ pgentry_t *pgt = NULL;
+ unsigned long done = 0;
+ unsigned long i;
+ int rc;
+
+ if ( !mfns )
+ {
+ printk("do_map_frames: no mfns supplied\n");
+ return;
+ }
+ DEBUG("va=%p n=0x%lx, mfns[0]=0x%lx stride=0x%lx incr=0x%lx prot=0x%lx\n",
+ va, n, mfns[0], stride, incr, prot);
+
+ if ( err )
+ memset(err, 0x00, n * sizeof(int));
+ while ( done < n )
+ {
+ unsigned long todo;
+
+ if ( err )
+ todo = 1;
+ else
+ todo = n - done;
+
+ if ( todo > MAP_BATCH )
+ todo = MAP_BATCH;
+
+ {
+ mmu_update_t mmu_updates[todo];
+
+ for ( i = 0; i < todo; i++, va += PAGE_SIZE, pgt++)
+ {
+ if ( !pgt || !(va & L1_MASK) )
+ pgt = need_pgt(va);
+
+ mmu_updates[i].ptr = virt_to_mach(pgt) | MMU_NORMAL_PT_UPDATE;
+ mmu_updates[i].val = ((pgentry_t)(mfns[(done + i) * stride] +
+ (done + i) * incr)
+ << PAGE_SHIFT) | prot;
+ }
+
+ rc = HYPERVISOR_mmu_update(mmu_updates, todo, NULL, id);
+ if ( rc < 0 )
+ {
+ if (err)
+ err[done * stride] = rc;
+ else {
+ printk("Map %ld (%lx, ...) at %p failed: %d.\n",
+ todo, mfns[done * stride] + done * incr, va, rc);
+ do_exit();
+ }
+ }
+ }
+ done += todo;
+ }
+}
+
+/*
+ * Map an array of MFNs contiguous into virtual address space. Virtual
+ * addresses are allocated from the on demand area.
+ */
+void *map_frames_ex(const unsigned long *mfns, unsigned long n,
+ unsigned long stride, unsigned long incr,
+ unsigned long alignment,
+ domid_t id, int *err, unsigned long prot)
+{
+ unsigned long va = allocate_ondemand(n, alignment);
+
+ if ( !va )
+ return NULL;
+
+ do_map_frames(va, mfns, n, stride, incr, id, err, prot);
+
+ return (void *)va;
+}
+
+/*
+ * Unmap nun_frames frames mapped at virtual address va.
+ */
+#define UNMAP_BATCH ((STACK_SIZE / 2) / sizeof(multicall_entry_t))
+int unmap_frames(unsigned long va, unsigned long num_frames)
+{
+ int n = UNMAP_BATCH;
+ multicall_entry_t call[n];
+ int ret;
+ int i;
+
+ ASSERT(!((unsigned long)va & ~PAGE_MASK));
+
+ DEBUG("va=%p, num=0x%lx\n", va, num_frames);
+
+ while ( num_frames ) {
+ if ( n > num_frames )
+ n = num_frames;
+
+ for ( i = 0; i < n; i++ )
+ {
+ int arg = 0;
+ /* simply update the PTE for the VA and invalidate TLB */
+ call[i].op = __HYPERVISOR_update_va_mapping;
+ call[i].args[arg++] = va;
+ call[i].args[arg++] = 0;
+#ifdef __i386__
+ call[i].args[arg++] = 0;
+#endif
+ call[i].args[arg++] = UVMF_INVLPG;
+
+ va += PAGE_SIZE;
+ }
+
+ ret = HYPERVISOR_multicall(call, n);
+ if ( ret )
+ {
+ printk("update_va_mapping hypercall failed with rc=%d.\n", ret);
+ return -ret;
+ }
+
+ for ( i = 0; i < n; i++ )
+ {
+ if ( call[i].result )
+ {
+ printk("update_va_mapping failed for with rc=%d.\n", ret);
+ return -(call[i].result);
+ }
+ }
+ num_frames -= n;
+ }
+ return 0;
+}
+
+/*
+ * Allocate pages which are contiguous in machine memory.
+ * Returns a VA to where they are mapped or 0 on failure.
+ *
+ * addr_bits indicates if the region has restrictions on where it is
+ * located. Typical values are 32 (if for example PCI devices can't access
+ * 64bit memory) or 0 for no restrictions.
+ *
+ * Allocated pages can be freed using the page allocators free_pages()
+ * function.
+ *
+ * based on Linux function xen_create_contiguous_region()
+ */
+#define MAX_CONTIG_ORDER 9 /* 2MB */
+unsigned long alloc_contig_pages(int order, unsigned int addr_bits)
+{
+ unsigned long in_va, va;
+ unsigned long in_frames[1UL << order], out_frames, mfn;
+ multicall_entry_t call[1UL << order];
+ unsigned int i, num_pages = 1UL << order;
+ int ret, exch_success;
+
+ /* pass in num_pages 'extends' of size 1 and
+ * request 1 extend of size 'order */
+ struct xen_memory_exchange exchange = {
+ .in = {
+ .nr_extents = num_pages,
+ .extent_order = 0,
+ .domid = DOMID_SELF
+ },
+ .out = {
+ .nr_extents = 1,
+ .extent_order = order,
+ .address_bits = addr_bits,
+ .domid = DOMID_SELF
+ },
+ .nr_exchanged = 0
+ };
+
+ if ( order > MAX_CONTIG_ORDER )
+ {
+ printk("alloc_contig_pages: order too large 0x%x > 0x%x\n",
+ order, MAX_CONTIG_ORDER);
+ return 0;
+ }
+
+ /* Allocate some potentially discontiguous pages */
+ in_va = alloc_pages(order);
+ if ( !in_va )
+ {
+ printk("alloc_contig_pages: could not get enough pages (order=0x%x\n",
+ order);
+ return 0;
+ }
+
+ /* set up arguments for exchange hyper call */
+ set_xen_guest_handle(exchange.in.extent_start, in_frames);
+ set_xen_guest_handle(exchange.out.extent_start, &out_frames);
+
+ /* unmap current frames, keep a list of MFNs */
+ for ( i = 0; i < num_pages; i++ )
+ {
+ int arg = 0;
+
+ va = in_va + (PAGE_SIZE * i);
+ in_frames[i] = virt_to_mfn(va);
+
+ /* update P2M mapping */
+ phys_to_machine_mapping[virt_to_pfn(va)] = INVALID_P2M_ENTRY;
+
+ /* build multi call */
+ call[i].op = __HYPERVISOR_update_va_mapping;
+ call[i].args[arg++] = va;
+ call[i].args[arg++] = 0;
+#ifdef __i386__
+ call[i].args[arg++] = 0;
+#endif
+ call[i].args[arg++] = UVMF_INVLPG;
+ }
+
+ ret = HYPERVISOR_multicall(call, i);
+ if ( ret )
+ {
+ printk("Odd, update_va_mapping hypercall failed with rc=%d.\n", ret);
+ return 0;
+ }
+
+ /* try getting a contig range of MFNs */
+ out_frames = virt_to_pfn(in_va); /* PFNs to populate */
+ ret = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
+ if ( ret ) {
+ printk("mem exchanged order=0x%x failed with rc=%d, nr_exchanged=%d\n",
+ order, ret, exchange.nr_exchanged);
+ /* we still need to return the allocated pages above to the pool
+ * ie. map them back into the 1:1 mapping etc. so we continue but
+ * in the end return the pages to the page allocator and return 0. */
+ exch_success = 0;
+ }
+ else
+ exch_success = 1;
+
+ /* map frames into 1:1 and update p2m */
+ for ( i = 0; i < num_pages; i++ )
+ {
+ int arg = 0;
+ pte_t pte;
+
+ va = in_va + (PAGE_SIZE * i);
+ mfn = i < exchange.nr_exchanged ? (out_frames + i) : in_frames[i];
+ pte = __pte(mfn << PAGE_SHIFT | L1_PROT);
+
+ /* update P2M mapping */
+ phys_to_machine_mapping[virt_to_pfn(va)] = mfn;
+
+ /* build multi call */
+ call[i].op = __HYPERVISOR_update_va_mapping;
+ call[i].args[arg++] = va;
+#ifdef __x86_64__
+ call[i].args[arg++] = (pgentry_t)pte.pte;
+#else
+ call[i].args[arg++] = pte.pte_low;
+ call[i].args[arg++] = pte.pte_high;
+#endif
+ call[i].args[arg++] = UVMF_INVLPG;
+ }
+ ret = HYPERVISOR_multicall(call, i);
+ if ( ret )
+ {
+ printk("update_va_mapping hypercall no. 2 failed with rc=%d.\n", ret);
+ return 0;
+ }
+
+ if ( !exch_success )
+ {
+ /* since the exchanged failed we just free the pages as well */
+ free_pages((void *) in_va, order);
+ return 0;
+ }
+
+ return in_va;
+}
+
+/*
+ * Clear some of the bootstrap memory
+ */
+static void clear_bootstrap(void)
+{
+ pte_t nullpte = { };
+ int rc;
+
+ /* Use first page as the CoW zero page */
+ memset(&_text, 0, PAGE_SIZE);
+ mfn_zero = virt_to_mfn((unsigned long) &_text);
+ if ( (rc = HYPERVISOR_update_va_mapping(0, nullpte, UVMF_INVLPG)) )
+ printk("Unable to unmap NULL page. rc=%d\n", rc);
+}
+
+void arch_init_p2m(unsigned long max_pfn)
+{
+#ifdef __x86_64__
+#define L1_P2M_SHIFT 9
+#define L2_P2M_SHIFT 18
+#define L3_P2M_SHIFT 27
+#else
+#define L1_P2M_SHIFT 10
+#define L2_P2M_SHIFT 20
+#define L3_P2M_SHIFT 30
+#endif
+#define L1_P2M_ENTRIES (1 << L1_P2M_SHIFT)
+#define L2_P2M_ENTRIES (1 << (L2_P2M_SHIFT - L1_P2M_SHIFT))
+#define L3_P2M_ENTRIES (1 << (L3_P2M_SHIFT - L2_P2M_SHIFT))
+#define L1_P2M_MASK (L1_P2M_ENTRIES - 1)
+#define L2_P2M_MASK (L2_P2M_ENTRIES - 1)
+#define L3_P2M_MASK (L3_P2M_ENTRIES - 1)
+
+ unsigned long *l1_list = NULL, *l2_list = NULL, *l3_list;
+ unsigned long pfn;
+
+ l3_list = (unsigned long *)alloc_page();
+ for ( pfn=0; pfn<max_pfn; pfn++ )
+ {
+ if ( !(pfn % (L1_P2M_ENTRIES * L2_P2M_ENTRIES)) )
+ {
+ l2_list = (unsigned long*)alloc_page();
+ if ( (pfn >> L3_P2M_SHIFT) > 0 )
+ {
+ printk("Error: Too many pfns.\n");
+ do_exit();
+ }
+ l3_list[(pfn >> L2_P2M_SHIFT)] = virt_to_mfn(l2_list);
+ }
+ if ( !(pfn % (L1_P2M_ENTRIES)) )
+ {
+ l1_list = (unsigned long*)alloc_page();
+ l2_list[(pfn >> L1_P2M_SHIFT) & L2_P2M_MASK] =
+ virt_to_mfn(l1_list);
+ }
+
+ l1_list[pfn & L1_P2M_MASK] = pfn_to_mfn(pfn);
+ }
+ HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+ virt_to_mfn(l3_list);
+ HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
+}
+
+void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p)
+{
+ unsigned long start_pfn, max_pfn;
+
+ printk(" _text: %p(VA)\n", &_text);
+ printk(" _etext: %p(VA)\n", &_etext);
+ printk(" _erodata: %p(VA)\n", &_erodata);
+ printk(" _edata: %p(VA)\n", &_edata);
+ printk("stack start: %p(VA)\n", stack);
+ printk(" _end: %p(VA)\n", &_end);
+
+ /* First page follows page table pages and 3 more pages (store page etc) */
+ start_pfn = PFN_UP(to_phys(start_info.pt_base)) +
+ start_info.nr_pt_frames + 3;
+ max_pfn = start_info.nr_pages;
+
+ /* We need room for demand mapping and heap, clip available memory */
+#if defined(__i386__)
+ {
+ unsigned long virt_pfns = 1 + DEMAND_MAP_PAGES + 1 + HEAP_PAGES;
+ if (max_pfn + virt_pfns >= 0x100000)
+ max_pfn = 0x100000 - virt_pfns - 1;
+ }
+#endif
+
+ printk(" start_pfn: %lx\n", start_pfn);
+ printk(" max_pfn: %lx\n", max_pfn);
+
+ build_pagetable(&start_pfn, &max_pfn);
+ clear_bootstrap();
+ set_readonly(&_text, &_erodata);
+
+ *start_pfn_p = start_pfn;
+ *max_pfn_p = max_pfn;
+}
+
+grant_entry_t *arch_init_gnttab(int nr_grant_frames)
+{
+ struct gnttab_setup_table setup;
+ unsigned long frames[nr_grant_frames];
+
+ setup.dom = DOMID_SELF;
+ setup.nr_frames = nr_grant_frames;
+ set_xen_guest_handle(setup.frame_list, frames);
+
+ HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+ return map_frames(frames, nr_grant_frames);
+}
--- /dev/null
+/*
+ ****************************************************************************
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: sched.c
+ * Author: Grzegorz Milos
+ * Changes: Robert Kaiser
+ *
+ * Date: Aug 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: simple scheduler for Mini-Os
+ *
+ * The scheduler is non-preemptive (cooperative), and schedules according
+ * to Round Robin algorithm.
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <mini-os/os.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/time.h>
+#include <mini-os/mm.h>
+#include <mini-os/types.h>
+#include <mini-os/lib.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/list.h>
+#include <mini-os/sched.h>
+#include <mini-os/semaphore.h>
+
+
+#ifdef SCHED_DEBUG
+#define DEBUG(_f, _a...) \
+ printk("MINI_OS(file=sched.c, line=%d) " _f "\n", __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...) ((void)0)
+#endif
+
+
+void dump_stack(struct thread *thread)
+{
+ unsigned long *bottom = (unsigned long *)(thread->stack + STACK_SIZE);
+ unsigned long *pointer = (unsigned long *)thread->sp;
+ int count;
+ if(thread == current)
+ {
+#ifdef __i386__
+ asm("movl %%esp,%0"
+ : "=r"(pointer));
+#else
+ asm("movq %%rsp,%0"
+ : "=r"(pointer));
+#endif
+ }
+ printk("The stack for \"%s\"\n", thread->name);
+ for(count = 0; count < 25 && pointer < bottom; count ++)
+ {
+ printk("[0x%lx] 0x%lx\n", pointer, *pointer);
+ pointer++;
+ }
+
+ if(pointer < bottom) printk(" ... continues.\n");
+}
+
+/* Gets run when a new thread is scheduled the first time ever,
+ defined in x86_[32/64].S */
+extern void thread_starter(void);
+
+/* Pushes the specified value onto the stack of the specified thread */
+static void stack_push(struct thread *thread, unsigned long value)
+{
+ thread->sp -= sizeof(unsigned long);
+ *((unsigned long *)thread->sp) = value;
+}
+
+/* Architecture specific setup of thread creation */
+struct thread* arch_create_thread(char *name, void (*function)(void *),
+ void *data)
+{
+ struct thread *thread;
+
+ thread = xmalloc(struct thread);
+ /* We can't use lazy allocation here since the trap handler runs on the stack */
+ thread->stack = (char *)alloc_pages(STACK_SIZE_PAGE_ORDER);
+ thread->name = name;
+ printk("Thread \"%s\": pointer: 0x%lx, stack: 0x%lx\n", name, thread,
+ thread->stack);
+
+ thread->sp = (unsigned long)thread->stack + STACK_SIZE;
+ /* Save pointer to the thread on the stack, used by current macro */
+ *((unsigned long *)thread->stack) = (unsigned long)thread;
+
+ /* Must ensure that (%rsp + 8) is 16-byte aligned at the start of thread_starter. */
+ thread->sp -= sizeof(unsigned long);
+
+ stack_push(thread, (unsigned long) function);
+ stack_push(thread, (unsigned long) data);
+ thread->ip = (unsigned long) thread_starter;
+ return thread;
+}
+
+void run_idle_thread(void)
+{
+ /* Switch stacks and run the thread */
+#if defined(__i386__)
+ __asm__ __volatile__("mov %0,%%esp\n\t"
+ "push %1\n\t"
+ "ret"
+ :"=m" (idle_thread->sp)
+ :"m" (idle_thread->ip));
+#elif defined(__x86_64__)
+ __asm__ __volatile__("mov %0,%%rsp\n\t"
+ "push %1\n\t"
+ "ret"
+ :"=m" (idle_thread->sp)
+ :"m" (idle_thread->ip));
+#endif
+}
+
+
+
--- /dev/null
+/******************************************************************************
+ * common.c
+ *
+ * Common stuff special to x86 goes here.
+ *
+ * Copyright (c) 2002-2003, K A Fraser & R Neugebauer
+ * Copyright (c) 2005, Grzegorz Milos, Intel Research Cambridge
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <mini-os/os.h>
+#include <mini-os/lib.h> /* for printk, memcpy */
+#include <mini-os/kernel.h>
+#include <xen/xen.h>
+
+/*
+ * Shared page for communicating with the hypervisor.
+ * Events flags go here, for example.
+ */
+shared_info_t *HYPERVISOR_shared_info;
+
+/*
+ * This structure contains start-of-day info, such as pagetable base pointer,
+ * address of the shared_info structure, and things like that.
+ */
+union start_info_union start_info_union;
+
+/*
+ * Just allocate the kernel stack here. SS:ESP is set up to point here
+ * in head.S.
+ */
+char stack[2*STACK_SIZE];
+
+extern char shared_info[PAGE_SIZE];
+
+/* Assembler interface fns in entry.S. */
+void hypervisor_callback(void);
+void failsafe_callback(void);
+
+#if defined(__x86_64__)
+#define __pte(x) ((pte_t) { (x) } )
+#else
+#define __pte(x) ({ unsigned long long _x = (x); \
+ ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
+#endif
+
+static
+shared_info_t *map_shared_info(unsigned long pa)
+{
+ int rc;
+
+ if ( (rc = HYPERVISOR_update_va_mapping(
+ (unsigned long)shared_info, __pte(pa | 7), UVMF_INVLPG)) )
+ {
+ printk("Failed to map shared_info!! rc=%d\n", rc);
+ do_exit();
+ }
+ return (shared_info_t *)shared_info;
+}
+
+static inline void fpu_init(void) {
+ asm volatile("fninit");
+}
+
+#ifdef __SSE__
+static inline void sse_init(void) {
+ unsigned long status = 0x1f80;
+ asm volatile("ldmxcsr %0" : : "m" (status));
+}
+#else
+#define sse_init()
+#endif
+
+
+/*
+ * INITIAL C ENTRY POINT.
+ */
+void
+arch_init(start_info_t *si)
+{
+ static char hello[] = "Bootstrapping...\n";
+
+ (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
+
+ trap_init();
+
+ /*Initialize floating point unit */
+ fpu_init();
+
+ /* Initialize SSE */
+ sse_init();
+
+ /* Copy the start_info struct to a globally-accessible area. */
+ /* WARN: don't do printk before here, it uses information from
+ shared_info. Use xprintk instead. */
+ memcpy(&start_info, si, sizeof(*si));
+
+ /* print out some useful information */
+ printk("Xen Minimal OS!\n");
+ printk(" start_info: %p(VA)\n", si);
+ printk(" nr_pages: 0x%lx\n", si->nr_pages);
+ printk(" shared_inf: 0x%08lx(MA)\n", si->shared_info);
+ printk(" pt_base: %p(VA)\n", (void *)si->pt_base);
+ printk("nr_pt_frames: 0x%lx\n", si->nr_pt_frames);
+ printk(" mfn_list: %p(VA)\n", (void *)si->mfn_list);
+ printk(" mod_start: 0x%lx(VA)\n", si->mod_start);
+ printk(" mod_len: %lu\n", si->mod_len);
+ printk(" flags: 0x%x\n", (unsigned int)si->flags);
+ printk(" cmd_line: %s\n",
+ si->cmd_line ? (const char *)si->cmd_line : "NULL");
+ printk(" stack: %p-%p\n", stack, stack + sizeof(stack));
+
+ /* set up minimal memory infos */
+ phys_to_machine_mapping = (unsigned long *)start_info.mfn_list;
+
+ /* Grab the shared_info pointer and put it in a safe place. */
+ HYPERVISOR_shared_info = map_shared_info(start_info.shared_info);
+
+ /* Set up event and failsafe callback addresses. */
+#ifdef __i386__
+ HYPERVISOR_set_callbacks(
+ __KERNEL_CS, (unsigned long)hypervisor_callback,
+ __KERNEL_CS, (unsigned long)failsafe_callback);
+#else
+ HYPERVISOR_set_callbacks(
+ (unsigned long)hypervisor_callback,
+ (unsigned long)failsafe_callback, 0);
+#endif
+
+ start_kernel();
+}
+
+void
+arch_fini(void)
+{
+ /* Reset traps */
+ trap_fini();
+
+#ifdef __i386__
+ HYPERVISOR_set_callbacks(0, 0, 0, 0);
+#else
+ HYPERVISOR_set_callbacks(0, 0, 0);
+#endif
+}
+
+void
+arch_do_exit(void)
+{
+ stack_walk();
+}
--- /dev/null
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2002-2003 - Keir Fraser - University of Cambridge
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ * (C) 2006 - Robert Kaiser - FH Wiesbaden
+ ****************************************************************************
+ *
+ * File: time.c
+ * Author: Rolf Neugebauer and Keir Fraser
+ * Changes: Grzegorz Milos
+ *
+ * Description: Simple time and timer functions
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include <mini-os/os.h>
+#include <mini-os/traps.h>
+#include <mini-os/types.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/events.h>
+#include <mini-os/time.h>
+#include <mini-os/lib.h>
+
+/************************************************************************
+ * Time functions
+ *************************************************************************/
+
+/* These are peridically updated in shared_info, and then copied here. */
+struct shadow_time_info {
+ uint64_t tsc_timestamp; /* TSC at last update of time vals. */
+ uint64_t system_timestamp; /* Time, in nanosecs, since boot. */
+ uint32_t tsc_to_nsec_mul;
+ uint32_t tsc_to_usec_mul;
+ int tsc_shift;
+ uint32_t version;
+};
+static struct timespec shadow_ts;
+static uint32_t shadow_ts_version;
+
+static struct shadow_time_info shadow;
+
+
+#ifndef rmb
+#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
+#endif
+
+#define HANDLE_USEC_OVERFLOW(_tv) \
+ do { \
+ while ( (_tv)->tv_usec >= 1000000 ) \
+ { \
+ (_tv)->tv_usec -= 1000000; \
+ (_tv)->tv_sec++; \
+ } \
+ } while ( 0 )
+
+static inline int time_values_up_to_date(void)
+{
+ struct vcpu_time_info *src = &HYPERVISOR_shared_info->vcpu_info[0].time;
+
+ return (shadow.version == src->version);
+}
+
+
+/*
+ * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
+ * yielding a 64-bit result.
+ */
+static inline uint64_t scale_delta(uint64_t delta, uint32_t mul_frac, int shift)
+{
+ uint64_t product;
+#ifdef __i386__
+ uint32_t tmp1, tmp2;
+#endif
+
+ if ( shift < 0 )
+ delta >>= -shift;
+ else
+ delta <<= shift;
+
+#ifdef __i386__
+ __asm__ (
+ "mul %5 ; "
+ "mov %4,%%eax ; "
+ "mov %%edx,%4 ; "
+ "mul %5 ; "
+ "add %4,%%eax ; "
+ "xor %5,%5 ; "
+ "adc %5,%%edx ; "
+ : "=A" (product), "=r" (tmp1), "=r" (tmp2)
+ : "a" ((uint32_t)delta), "1" ((uint32_t)(delta >> 32)), "2" (mul_frac) );
+#else
+ __asm__ (
+ "mul %%rdx ; shrd $32,%%rdx,%%rax"
+ : "=a" (product) : "0" (delta), "d" ((uint64_t)mul_frac) );
+#endif
+
+ return product;
+}
+
+
+static unsigned long get_nsec_offset(void)
+{
+ uint64_t now, delta;
+ rdtscll(now);
+ delta = now - shadow.tsc_timestamp;
+ return scale_delta(delta, shadow.tsc_to_nsec_mul, shadow.tsc_shift);
+}
+
+
+static void get_time_values_from_xen(void)
+{
+ struct vcpu_time_info *src = &HYPERVISOR_shared_info->vcpu_info[0].time;
+
+ do {
+ shadow.version = src->version;
+ rmb();
+ shadow.tsc_timestamp = src->tsc_timestamp;
+ shadow.system_timestamp = src->system_time;
+ shadow.tsc_to_nsec_mul = src->tsc_to_system_mul;
+ shadow.tsc_shift = src->tsc_shift;
+ rmb();
+ }
+ while ((src->version & 1) | (shadow.version ^ src->version));
+
+ shadow.tsc_to_usec_mul = shadow.tsc_to_nsec_mul / 1000;
+}
+
+
+
+
+/* monotonic_clock(): returns # of nanoseconds passed since time_init()
+ * Note: This function is required to return accurate
+ * time even in the absence of multiple timer ticks.
+ */
+uint64_t monotonic_clock(void)
+{
+ uint64_t time;
+ uint32_t local_time_version;
+
+ do {
+ local_time_version = shadow.version;
+ rmb();
+ time = shadow.system_timestamp + get_nsec_offset();
+ if (!time_values_up_to_date())
+ get_time_values_from_xen();
+ rmb();
+ } while (local_time_version != shadow.version);
+
+ return time;
+}
+
+static void update_wallclock(void)
+{
+ shared_info_t *s = HYPERVISOR_shared_info;
+
+ do {
+ shadow_ts_version = s->wc_version;
+ rmb();
+ shadow_ts.tv_sec = s->wc_sec;
+ shadow_ts.tv_nsec = s->wc_nsec;
+ rmb();
+ }
+ while ((s->wc_version & 1) | (shadow_ts_version ^ s->wc_version));
+}
+
+
+int gettimeofday(struct timeval *tv, void *tz)
+{
+ uint64_t nsec = monotonic_clock();
+ nsec += shadow_ts.tv_nsec;
+
+
+ tv->tv_sec = shadow_ts.tv_sec;
+ tv->tv_sec += NSEC_TO_SEC(nsec);
+ tv->tv_usec = NSEC_TO_USEC(nsec % 1000000000UL);
+
+ return 0;
+}
+
+
+void block_domain(s_time_t until)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ ASSERT(irqs_disabled());
+ if(monotonic_clock() < until)
+ {
+ HYPERVISOR_set_timer_op(until);
+ HYPERVISOR_sched_op(SCHEDOP_block, 0);
+ local_irq_disable();
+ }
+}
+
+
+/*
+ * Just a dummy
+ */
+static void timer_handler(evtchn_port_t ev, struct pt_regs *regs, void *ign)
+{
+ get_time_values_from_xen();
+ update_wallclock();
+}
+
+
+
+static evtchn_port_t port;
+void init_time(void)
+{
+ printk("Initialising timer interface\n");
+ port = bind_virq(VIRQ_TIMER, &timer_handler, NULL);
+ unmask_evtchn(port);
+}
+
+void fini_time(void)
+{
+ /* Clear any pending timer */
+ HYPERVISOR_set_timer_op(0);
+ unbind_evtchn(port);
+}
--- /dev/null
+
+#include <mini-os/os.h>
+#include <mini-os/traps.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/mm.h>
+#include <mini-os/lib.h>
+#include <mini-os/sched.h>
+
+/*
+ * These are assembler stubs in entry.S.
+ * They are the actual entry points for virtual exceptions.
+ */
+void divide_error(void);
+void debug(void);
+void int3(void);
+void overflow(void);
+void bounds(void);
+void invalid_op(void);
+void device_not_available(void);
+void coprocessor_segment_overrun(void);
+void invalid_TSS(void);
+void segment_not_present(void);
+void stack_segment(void);
+void general_protection(void);
+void page_fault(void);
+void coprocessor_error(void);
+void simd_coprocessor_error(void);
+void alignment_check(void);
+void spurious_interrupt_bug(void);
+void machine_check(void);
+
+
+void dump_regs(struct pt_regs *regs)
+{
+ printk("Thread: %s\n", current->name);
+#ifdef __i386__
+ printk("EIP: %x, EFLAGS %x.\n", regs->eip, regs->eflags);
+ printk("EBX: %08x ECX: %08x EDX: %08x\n",
+ regs->ebx, regs->ecx, regs->edx);
+ printk("ESI: %08x EDI: %08x EBP: %08x EAX: %08x\n",
+ regs->esi, regs->edi, regs->ebp, regs->eax);
+ printk("DS: %04x ES: %04x orig_eax: %08x, eip: %08x\n",
+ regs->xds, regs->xes, regs->orig_eax, regs->eip);
+ printk("CS: %04x EFLAGS: %08x esp: %08x ss: %04x\n",
+ regs->xcs, regs->eflags, regs->esp, regs->xss);
+#else
+ printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip);
+ printk("\nRSP: %04lx:%016lx EFLAGS: %08lx\n",
+ regs->ss, regs->rsp, regs->eflags);
+ printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
+ regs->rax, regs->rbx, regs->rcx);
+ printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
+ regs->rdx, regs->rsi, regs->rdi);
+ printk("RBP: %016lx R08: %016lx R09: %016lx\n",
+ regs->rbp, regs->r8, regs->r9);
+ printk("R10: %016lx R11: %016lx R12: %016lx\n",
+ regs->r10, regs->r11, regs->r12);
+ printk("R13: %016lx R14: %016lx R15: %016lx\n",
+ regs->r13, regs->r14, regs->r15);
+#endif
+}
+
+static void do_trap(int trapnr, char *str, struct pt_regs * regs, unsigned long error_code)
+{
+ printk("FATAL: Unhandled Trap %d (%s), error code=0x%lx\n", trapnr, str, error_code);
+ printk("Regs address %p\n", regs);
+ dump_regs(regs);
+ do_exit();
+}
+
+#define DO_ERROR(trapnr, str, name) \
+void do_##name(struct pt_regs * regs, unsigned long error_code) \
+{ \
+ do_trap(trapnr, str, regs, error_code); \
+}
+
+#define DO_ERROR_INFO(trapnr, str, name, sicode, siaddr) \
+void do_##name(struct pt_regs * regs, unsigned long error_code) \
+{ \
+ do_trap(trapnr, str, regs, error_code); \
+}
+
+DO_ERROR_INFO( 0, "divide error", divide_error, FPE_INTDIV, regs->eip)
+DO_ERROR( 3, "int3", int3)
+DO_ERROR( 4, "overflow", overflow)
+DO_ERROR( 5, "bounds", bounds)
+DO_ERROR_INFO( 6, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
+DO_ERROR( 7, "device not available", device_not_available)
+DO_ERROR( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
+DO_ERROR(10, "invalid TSS", invalid_TSS)
+DO_ERROR(11, "segment not present", segment_not_present)
+DO_ERROR(12, "stack segment", stack_segment)
+DO_ERROR_INFO(17, "alignment check", alignment_check, BUS_ADRALN, 0)
+DO_ERROR(18, "machine check", machine_check)
+
+void page_walk(unsigned long virt_address)
+{
+ pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
+ unsigned long addr = virt_address;
+ printk("Pagetable walk from virt %lx, base %lx:\n", virt_address, start_info.pt_base);
+
+#if defined(__x86_64__)
+ page = tab[l4_table_offset(addr)];
+ tab = pte_to_virt(page);
+ printk(" L4 = %"PRIpte" (%p) [offset = %lx]\n", page, tab, l4_table_offset(addr));
+#endif
+ page = tab[l3_table_offset(addr)];
+ tab = pte_to_virt(page);
+ printk(" L3 = %"PRIpte" (%p) [offset = %lx]\n", page, tab, l3_table_offset(addr));
+ page = tab[l2_table_offset(addr)];
+ tab = pte_to_virt(page);
+ printk(" L2 = %"PRIpte" (%p) [offset = %lx]\n", page, tab, l2_table_offset(addr));
+
+ page = tab[l1_table_offset(addr)];
+ printk(" L1 = %"PRIpte" [offset = %lx]\n", page, l1_table_offset(addr));
+
+}
+
+static int handle_cow(unsigned long addr) {
+ pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
+ unsigned long new_page;
+ int rc;
+
+#if defined(__x86_64__)
+ page = tab[l4_table_offset(addr)];
+ if (!(page & _PAGE_PRESENT))
+ return 0;
+ tab = pte_to_virt(page);
+#endif
+ page = tab[l3_table_offset(addr)];
+ if (!(page & _PAGE_PRESENT))
+ return 0;
+ tab = pte_to_virt(page);
+
+ page = tab[l2_table_offset(addr)];
+ if (!(page & _PAGE_PRESENT))
+ return 0;
+ tab = pte_to_virt(page);
+
+ page = tab[l1_table_offset(addr)];
+ if (!(page & _PAGE_PRESENT))
+ return 0;
+ /* Only support CoW for the zero page. */
+ if (PHYS_PFN(page) != mfn_zero)
+ return 0;
+
+ new_page = alloc_pages(0);
+ memset((void*) new_page, 0, PAGE_SIZE);
+
+ rc = HYPERVISOR_update_va_mapping(addr & PAGE_MASK, __pte(virt_to_mach(new_page) | L1_PROT), UVMF_INVLPG);
+ if (!rc)
+ return 1;
+
+ printk("Map zero page to %lx failed: %d.\n", addr, rc);
+ return 0;
+}
+
+static void do_stack_walk(unsigned long frame_base)
+{
+ unsigned long *frame = (void*) frame_base;
+ printk("base is %#lx ", frame_base);
+ printk("caller is %#lx\n", frame[1]);
+ if (frame[0])
+ do_stack_walk(frame[0]);
+}
+
+void stack_walk(void)
+{
+ unsigned long bp;
+#ifdef __x86_64__
+ asm("movq %%rbp, %0":"=r"(bp));
+#else
+ asm("movl %%ebp, %0":"=r"(bp));
+#endif
+ do_stack_walk(bp);
+}
+
+static void dump_mem(unsigned long addr)
+{
+ unsigned long i;
+ if (addr < PAGE_SIZE)
+ return;
+
+ for (i = ((addr)-16 ) & ~15; i < (((addr)+48 ) & ~15); i++)
+ {
+ if (!(i%16))
+ printk("\n%lx:", i);
+ printk(" %02x", *(unsigned char *)i);
+ }
+ printk("\n");
+}
+#define read_cr2() \
+ (HYPERVISOR_shared_info->vcpu_info[smp_processor_id()].arch.cr2)
+
+static int handling_pg_fault = 0;
+
+void do_page_fault(struct pt_regs *regs, unsigned long error_code)
+{
+ unsigned long addr = read_cr2();
+ struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_crash };
+
+ if ((error_code & TRAP_PF_WRITE) && handle_cow(addr))
+ return;
+
+ /* If we are already handling a page fault, and got another one
+ that means we faulted in pagetable walk. Continuing here would cause
+ a recursive fault */
+ if(handling_pg_fault == 1)
+ {
+ printk("Page fault in pagetable walk (access to invalid memory?).\n");
+ HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
+ }
+ handling_pg_fault++;
+ barrier();
+
+#if defined(__x86_64__)
+ printk("Page fault at linear address %p, rip %p, regs %p, sp %p, our_sp %p, code %lx\n",
+ addr, regs->rip, regs, regs->rsp, &addr, error_code);
+#else
+ printk("Page fault at linear address %p, eip %p, regs %p, sp %p, our_sp %p, code %lx\n",
+ addr, regs->eip, regs, regs->esp, &addr, error_code);
+#endif
+
+ dump_regs(regs);
+#if defined(__x86_64__)
+ do_stack_walk(regs->rbp);
+ dump_mem(regs->rsp);
+ dump_mem(regs->rbp);
+ dump_mem(regs->rip);
+#else
+ do_stack_walk(regs->ebp);
+ dump_mem(regs->esp);
+ dump_mem(regs->ebp);
+ dump_mem(regs->eip);
+#endif
+ page_walk(addr);
+ HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
+ /* We should never get here ... but still */
+ handling_pg_fault--;
+}
+
+void do_general_protection(struct pt_regs *regs, long error_code)
+{
+ struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_crash };
+#ifdef __i386__
+ printk("GPF eip: %p, error_code=%lx\n", regs->eip, error_code);
+#else
+ printk("GPF rip: %p, error_code=%lx\n", regs->rip, error_code);
+#endif
+ dump_regs(regs);
+#if defined(__x86_64__)
+ do_stack_walk(regs->rbp);
+ dump_mem(regs->rsp);
+ dump_mem(regs->rbp);
+ dump_mem(regs->rip);
+#else
+ do_stack_walk(regs->ebp);
+ dump_mem(regs->esp);
+ dump_mem(regs->ebp);
+ dump_mem(regs->eip);
+#endif
+ HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
+}
+
+
+void do_debug(struct pt_regs * regs)
+{
+ printk("Debug exception\n");
+#define TF_MASK 0x100
+ regs->eflags &= ~TF_MASK;
+ dump_regs(regs);
+ do_exit();
+}
+
+void do_coprocessor_error(struct pt_regs * regs)
+{
+ printk("Copro error\n");
+ dump_regs(regs);
+ do_exit();
+}
+
+void simd_math_error(void *eip)
+{
+ printk("SIMD error\n");
+}
+
+void do_simd_coprocessor_error(struct pt_regs * regs)
+{
+ printk("SIMD copro error\n");
+}
+
+void do_spurious_interrupt_bug(struct pt_regs * regs)
+{
+}
+
+/*
+ * Submit a virtual IDT to teh hypervisor. This consists of tuples
+ * (interrupt vector, privilege ring, CS:EIP of handler).
+ * The 'privilege ring' field specifies the least-privileged ring that
+ * can trap to that vector using a software-interrupt instruction (INT).
+ */
+static trap_info_t trap_table[] = {
+ { 0, 0, __KERNEL_CS, (unsigned long)divide_error },
+ { 1, 0, __KERNEL_CS, (unsigned long)debug },
+ { 3, 3, __KERNEL_CS, (unsigned long)int3 },
+ { 4, 3, __KERNEL_CS, (unsigned long)overflow },
+ { 5, 3, __KERNEL_CS, (unsigned long)bounds },
+ { 6, 0, __KERNEL_CS, (unsigned long)invalid_op },
+ { 7, 0, __KERNEL_CS, (unsigned long)device_not_available },
+ { 9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
+ { 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS },
+ { 11, 0, __KERNEL_CS, (unsigned long)segment_not_present },
+ { 12, 0, __KERNEL_CS, (unsigned long)stack_segment },
+ { 13, 0, __KERNEL_CS, (unsigned long)general_protection },
+ { 14, 0, __KERNEL_CS, (unsigned long)page_fault },
+ { 15, 0, __KERNEL_CS, (unsigned long)spurious_interrupt_bug },
+ { 16, 0, __KERNEL_CS, (unsigned long)coprocessor_error },
+ { 17, 0, __KERNEL_CS, (unsigned long)alignment_check },
+ { 19, 0, __KERNEL_CS, (unsigned long)simd_coprocessor_error },
+ { 0, 0, 0, 0 }
+};
+
+
+
+void trap_init(void)
+{
+ HYPERVISOR_set_trap_table(trap_table);
+}
+
+void trap_fini(void)
+{
+ HYPERVISOR_set_trap_table(NULL);
+}
--- /dev/null
+#include <mini-os/os.h>
+#include <mini-os/x86/arch_limits.h>
+#include <xen/arch-x86_32.h>
+
+.section __xen_guest
+ .ascii "GUEST_OS=Mini-OS"
+ .ascii ",XEN_VER=xen-3.0"
+ .ascii ",VIRT_BASE=0x0" /* &_text from minios_x86_32.lds */
+ .ascii ",ELF_PADDR_OFFSET=0x0"
+ .ascii ",HYPERCALL_PAGE=0x2"
+ .ascii ",PAE=yes[extended-cr3]"
+ .ascii ",LOADER=generic"
+ .byte 0
+.text
+
+.globl _start, shared_info, hypercall_page
+
+_start:
+ cld
+ lss stack_start,%esp
+ andl $(~(__STACK_SIZE-1)), %esp
+ push %esi
+ call arch_init
+
+stack_start:
+ .long stack+(2*__STACK_SIZE), __KERNEL_SS
+
+ /* Unpleasant -- the PTE that maps this page is actually overwritten */
+ /* to map the real shared-info page! :-) */
+ .org 0x1000
+shared_info:
+ .org 0x2000
+
+hypercall_page:
+ .org 0x3000
+
+ES = 0x20
+ORIG_EAX = 0x24
+EIP = 0x28
+CS = 0x2C
+
+#define ENTRY(X) .globl X ; X :
+
+#define SAVE_ALL \
+ cld; \
+ pushl %es; \
+ pushl %ds; \
+ pushl %eax; \
+ pushl %ebp; \
+ pushl %edi; \
+ pushl %esi; \
+ pushl %edx; \
+ pushl %ecx; \
+ pushl %ebx; \
+ movl $(__KERNEL_DS),%edx; \
+ movl %edx,%ds; \
+ movl %edx,%es;
+
+#define RESTORE_ALL \
+ popl %ebx; \
+ popl %ecx; \
+ popl %edx; \
+ popl %esi; \
+ popl %edi; \
+ popl %ebp; \
+ popl %eax; \
+ popl %ds; \
+ popl %es; \
+ addl $4,%esp; \
+ iret;
+
+ENTRY(divide_error)
+ pushl $0 # no error code
+ pushl $do_divide_error
+do_exception:
+ pushl %ds
+ pushl %eax
+ xorl %eax, %eax
+ pushl %ebp
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ decl %eax # eax = -1
+ pushl %ecx
+ pushl %ebx
+ cld
+ movl %es, %ecx
+ movl ES(%esp), %edi # get the function address
+ movl ORIG_EAX(%esp), %edx # get the error code
+ movl %eax, ORIG_EAX(%esp)
+ movl %ecx, ES(%esp)
+ movl $(__KERNEL_DS), %ecx
+ movl %ecx, %ds
+ movl %ecx, %es
+ movl %esp,%eax # pt_regs pointer
+ pushl %edx
+ pushl %eax
+ call *%edi
+ jmp ret_from_exception
+
+ret_from_exception:
+ movb CS(%esp),%cl
+ addl $8,%esp
+ RESTORE_ALL
+
+# A note on the "critical region" in our callback handler.
+# We want to avoid stacking callback handlers due to events occurring
+# during handling of the last event. To do this, we keep events disabled
+# until weve done all processing. HOWEVER, we must enable events before
+# popping the stack frame (cant be done atomically) and so it would still
+# be possible to get enough handler activations to overflow the stack.
+# Although unlikely, bugs of that kind are hard to track down, so wed
+# like to avoid the possibility.
+# So, on entry to the handler we detect whether we interrupted an
+# existing activation in its critical region -- if so, we pop the current
+# activation and restart the handler using the previous one.
+ENTRY(hypervisor_callback)
+ pushl %eax
+ SAVE_ALL
+ movl EIP(%esp),%eax
+ cmpl $scrit,%eax
+ jb 11f
+ cmpl $ecrit,%eax
+ jb critical_region_fixup
+11: push %esp
+ xorl %ebp,%ebp
+ call do_hypervisor_callback
+ add $4,%esp
+ movl HYPERVISOR_shared_info,%esi
+ xorl %eax,%eax
+ movb CS(%esp),%cl
+ test $2,%cl # slow return to ring 2 or 3
+ jne safesti
+safesti:movb $0,1(%esi) # reenable event callbacks
+scrit: /**** START OF CRITICAL REGION ****/
+ testb $0xFF,(%esi)
+ jnz 14f # process more events if necessary...
+ RESTORE_ALL
+14: movb $1,1(%esi)
+ jmp 11b
+ecrit: /**** END OF CRITICAL REGION ****/
+# [How we do the fixup]. We want to merge the current stack frame with the
+# just-interrupted frame. How we do this depends on where in the critical
+# region the interrupted handler was executing, and so how many saved
+# registers are in each frame. We do this quickly using the lookup table
+# 'critical_fixup_table'. For each byte offset in the critical region, it
+# provides the number of bytes which have already been popped from the
+# interrupted stack frame.
+critical_region_fixup:
+ addl $critical_fixup_table-scrit,%eax
+ movzbl (%eax),%eax # %eax contains num bytes popped
+ mov %esp,%esi
+ add %eax,%esi # %esi points at end of src region
+ mov %esp,%edi
+ add $0x34,%edi # %edi points at end of dst region
+ mov %eax,%ecx
+ shr $2,%ecx # convert words to bytes
+ je 16f # skip loop if nothing to copy
+15: subl $4,%esi # pre-decrementing copy loop
+ subl $4,%edi
+ movl (%esi),%eax
+ movl %eax,(%edi)
+ loop 15b
+16: movl %edi,%esp # final %edi is top of merged stack
+ jmp 11b
+
+critical_fixup_table:
+ .byte 0x00,0x00,0x00 # testb $0xff,(%esi)
+ .byte 0x00,0x00 # jne 14f
+ .byte 0x00 # pop %ebx
+ .byte 0x04 # pop %ecx
+ .byte 0x08 # pop %edx
+ .byte 0x0c # pop %esi
+ .byte 0x10 # pop %edi
+ .byte 0x14 # pop %ebp
+ .byte 0x18 # pop %eax
+ .byte 0x1c # pop %ds
+ .byte 0x20 # pop %es
+ .byte 0x24,0x24,0x24 # add $4,%esp
+ .byte 0x28 # iret
+ .byte 0x00,0x00,0x00,0x00 # movb $1,1(%esi)
+ .byte 0x00,0x00 # jmp 11b
+
+# Hypervisor uses this for application faults while it executes.
+ENTRY(failsafe_callback)
+ pop %ds
+ pop %es
+ pop %fs
+ pop %gs
+ iret
+
+ENTRY(coprocessor_error)
+ pushl $0
+ pushl $do_coprocessor_error
+ jmp do_exception
+
+ENTRY(simd_coprocessor_error)
+ pushl $0
+ pushl $do_simd_coprocessor_error
+ jmp do_exception
+
+ENTRY(device_not_available)
+ iret
+
+ENTRY(debug)
+ pushl $0
+ pushl $do_debug
+ jmp do_exception
+
+ENTRY(int3)
+ pushl $0
+ pushl $do_int3
+ jmp do_exception
+
+ENTRY(overflow)
+ pushl $0
+ pushl $do_overflow
+ jmp do_exception
+
+ENTRY(bounds)
+ pushl $0
+ pushl $do_bounds
+ jmp do_exception
+
+ENTRY(invalid_op)
+ pushl $0
+ pushl $do_invalid_op
+ jmp do_exception
+
+
+ENTRY(coprocessor_segment_overrun)
+ pushl $0
+ pushl $do_coprocessor_segment_overrun
+ jmp do_exception
+
+
+ENTRY(invalid_TSS)
+ pushl $do_invalid_TSS
+ jmp do_exception
+
+
+ENTRY(segment_not_present)
+ pushl $do_segment_not_present
+ jmp do_exception
+
+
+ENTRY(stack_segment)
+ pushl $do_stack_segment
+ jmp do_exception
+
+
+ENTRY(general_protection)
+ pushl $do_general_protection
+ jmp do_exception
+
+
+ENTRY(alignment_check)
+ pushl $do_alignment_check
+ jmp do_exception
+
+
+ENTRY(page_fault)
+ pushl $do_page_fault
+ jmp do_exception
+
+ENTRY(machine_check)
+ pushl $0
+ pushl $do_machine_check
+ jmp do_exception
+
+
+ENTRY(spurious_interrupt_bug)
+ pushl $0
+ pushl $do_spurious_interrupt_bug
+ jmp do_exception
+
+
+
+ENTRY(thread_starter)
+ popl %eax
+ popl %ebx
+ pushl $0
+ xorl %ebp,%ebp
+ pushl %eax
+ call *%ebx
+ call exit_thread
+
+ENTRY(__arch_switch_threads)
+ movl 4(%esp), %ecx /* prev */
+ movl 8(%esp), %edx /* next */
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl %esp, (%ecx) /* save ESP */
+ movl (%edx), %esp /* restore ESP */
+ movl $1f, 4(%ecx) /* save EIP */
+ pushl 4(%edx) /* restore EIP */
+ ret
+1:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
--- /dev/null
+#include <mini-os/os.h>
+#include <mini-os/x86/arch_limits.h>
+#include <xen/features.h>
+
+.section __xen_guest
+ .ascii "GUEST_OS=Mini-OS"
+ .ascii ",XEN_VER=xen-3.0"
+ .ascii ",VIRT_BASE=0x0" /* &_text from minios_x86_64.lds */
+ .ascii ",ELF_PADDR_OFFSET=0x0"
+ .ascii ",HYPERCALL_PAGE=0x2"
+ .ascii ",LOADER=generic"
+ .byte 0
+.text
+
+#define ENTRY(X) .globl X ; X :
+.globl _start, shared_info, hypercall_page
+
+
+_start:
+ cld
+ movq stack_start(%rip),%rsp
+ andq $(~(__STACK_SIZE-1)), %rsp
+ movq %rsi,%rdi
+ call arch_init
+
+stack_start:
+ .quad stack+(2*__STACK_SIZE)
+
+ /* Unpleasant -- the PTE that maps this page is actually overwritten */
+ /* to map the real shared-info page! :-) */
+ .org 0x1000
+shared_info:
+ .org 0x2000
+
+hypercall_page:
+ .org 0x3000
+
+
+#define XEN_GET_VCPU_INFO(reg) movq HYPERVISOR_shared_info,reg
+#define XEN_PUT_VCPU_INFO(reg)
+#define XEN_PUT_VCPU_INFO_fixup
+#define XEN_LOCKED_BLOCK_EVENTS(reg) movb $1,evtchn_upcall_mask(reg)
+#define XEN_LOCKED_UNBLOCK_EVENTS(reg) movb $0,evtchn_upcall_mask(reg)
+#define XEN_TEST_PENDING(reg) testb $0xFF,evtchn_upcall_pending(reg)
+
+#define XEN_BLOCK_EVENTS(reg) XEN_GET_VCPU_INFO(reg) ; \
+ XEN_LOCKED_BLOCK_EVENTS(reg) ; \
+ XEN_PUT_VCPU_INFO(reg)
+
+#define XEN_UNBLOCK_EVENTS(reg) XEN_GET_VCPU_INFO(reg) ; \
+ XEN_LOCKED_UNBLOCK_EVENTS(reg) ; \
+ XEN_PUT_VCPU_INFO(reg)
+
+
+/* Offsets into shared_info_t. */
+#define evtchn_upcall_pending /* 0 */
+#define evtchn_upcall_mask 1
+
+NMI_MASK = 0x80000000
+KERNEL_CS_MASK = 0xfc
+
+#define RAX 80
+#define RDI 112
+#define ORIG_RAX 120 /* + error_code */
+#define RIP 128
+#define CS 136
+#define RFLAGS 144
+#define RSP 152
+
+
+/* Macros */
+.macro zeroentry sym
+ movq (%rsp),%rcx
+ movq 8(%rsp),%r11
+ addq $0x10,%rsp /* skip rcx and r11 */
+ pushq $0 /* push error code/oldrax */
+ pushq %rax /* push real oldrax to the rdi slot */
+ leaq \sym(%rip),%rax
+ jmp error_entry
+.endm
+
+.macro errorentry sym
+ movq (%rsp),%rcx
+ movq 8(%rsp),%r11
+ addq $0x10,%rsp /* rsp points to the error code */
+ pushq %rax
+ leaq \sym(%rip),%rax
+ jmp error_entry
+.endm
+
+.macro RESTORE_ALL
+ movq (%rsp),%r11
+ movq 1*8(%rsp),%r10
+ movq 2*8(%rsp),%r9
+ movq 3*8(%rsp),%r8
+ movq 4*8(%rsp),%rax
+ movq 5*8(%rsp),%rcx
+ movq 6*8(%rsp),%rdx
+ movq 7*8(%rsp),%rsi
+ movq 8*8(%rsp),%rdi
+ addq $9*8+8,%rsp
+.endm
+
+.macro RESTORE_REST
+ movq (%rsp),%r15
+ movq 1*8(%rsp),%r14
+ movq 2*8(%rsp),%r13
+ movq 3*8(%rsp),%r12
+ movq 4*8(%rsp),%rbp
+ movq 5*8(%rsp),%rbx
+ addq $6*8,%rsp
+.endm
+
+.macro SAVE_REST
+ subq $6*8,%rsp
+ movq %rbx,5*8(%rsp)
+ movq %rbp,4*8(%rsp)
+ movq %r12,3*8(%rsp)
+ movq %r13,2*8(%rsp)
+ movq %r14,1*8(%rsp)
+ movq %r15,(%rsp)
+.endm
+
+.macro HYPERVISOR_IRET flag
+ testl $NMI_MASK,2*8(%rsp)
+ jnz 2f
+
+ /* Direct iret to kernel space. Correct CS and SS. */
+ orb $3,1*8(%rsp)
+ orb $3,4*8(%rsp)
+ iretq
+
+2: /* Slow iret via hypervisor. */
+ andl $~NMI_MASK, 16(%rsp)
+ pushq $\flag
+ jmp hypercall_page + (__HYPERVISOR_iret * 32)
+.endm
+
+
+/*
+ * Exception entry point. This expects an error code/orig_rax on the stack
+ * and the exception handler in %rax.
+ */
+ENTRY(error_entry)
+ /* rdi slot contains rax, oldrax contains error code */
+ cld
+ subq $14*8,%rsp
+ movq %rsi,13*8(%rsp)
+ movq 14*8(%rsp),%rsi /* load rax from rdi slot */
+ movq %rdx,12*8(%rsp)
+ movq %rcx,11*8(%rsp)
+ movq %rsi,10*8(%rsp) /* store rax */
+ movq %r8, 9*8(%rsp)
+ movq %r9, 8*8(%rsp)
+ movq %r10,7*8(%rsp)
+ movq %r11,6*8(%rsp)
+ movq %rbx,5*8(%rsp)
+ movq %rbp,4*8(%rsp)
+ movq %r12,3*8(%rsp)
+ movq %r13,2*8(%rsp)
+ movq %r14,1*8(%rsp)
+ movq %r15,(%rsp)
+
+error_call_handler:
+ movq %rdi, RDI(%rsp)
+ movq %rsp,%rdi
+ movq ORIG_RAX(%rsp),%rsi # get error code
+ movq $-1,ORIG_RAX(%rsp)
+ call *%rax
+ jmp error_exit
+
+
+/*
+ * Xen event (virtual interrupt) entry point.
+ */
+ENTRY(hypervisor_callback)
+ zeroentry hypervisor_callback2
+
+ENTRY(hypervisor_callback2)
+ movq %rdi, %rsp
+
+ /* check against event re-entrant */
+ movq RIP(%rsp),%rax
+ cmpq $scrit,%rax
+ jb 11f
+ cmpq $ecrit,%rax
+ jb critical_region_fixup
+
+11: movq %gs:8,%rax
+ incl %gs:0
+ cmovzq %rax,%rsp
+ pushq %rdi
+ call do_hypervisor_callback
+ popq %rsp
+ decl %gs:0
+
+error_exit:
+retint_kernel:
+ movl RFLAGS(%rsp), %eax
+ shr $9, %eax # EAX[0] == IRET_RFLAGS.IF
+ XEN_GET_VCPU_INFO(%rsi)
+ andb evtchn_upcall_mask(%rsi),%al
+ andb $1,%al # EAX[0] == IRET_RFLAGS.IF & event_mask
+ jnz restore_all_enable_events # != 0 => enable event delivery
+ XEN_PUT_VCPU_INFO(%rsi)
+
+retint_restore_args:
+ RESTORE_REST
+ RESTORE_ALL
+ HYPERVISOR_IRET 0
+
+restore_all_enable_events:
+ RESTORE_REST
+ RESTORE_ALL
+ pushq %rax # save rax for it will be clobbered later
+ RSP_OFFSET=8 # record the stack frame layout changes
+ XEN_GET_VCPU_INFO(%rax) # safe to use rax since it is saved
+ XEN_UNBLOCK_EVENTS(%rax)
+
+scrit: /**** START OF CRITICAL REGION ****/
+ XEN_TEST_PENDING(%rax)
+ jz 12f
+ XEN_LOCKED_BLOCK_EVENTS(%rax) # if pending, mask events and handle
+ # by jumping to hypervisor_prologue
+12: popq %rax # all registers restored from this point
+
+restore_end:
+ jnz hypervisor_prologue # safe to jump out of critical region
+ # because events are masked if ZF = 0
+ HYPERVISOR_IRET 0
+ecrit: /**** END OF CRITICAL REGION ****/
+
+# Set up the stack as Xen does before calling event callback
+hypervisor_prologue:
+ pushq %r11
+ pushq %rcx
+ jmp hypervisor_callback
+
+# [How we do the fixup]. We want to merge the current stack frame with the
+# just-interrupted frame. How we do this depends on where in the critical
+# region the interrupted handler was executing, and so if rax has been
+# restored. We determine by comparing interrupted rip with "restore_end".
+# We always copy all registers below RIP from the current stack frame
+# to the end of the previous activation frame so that we can continue
+# as if we've never even reached 11 running in the old activation frame.
+
+critical_region_fixup:
+ # Set up source and destination region pointers
+ leaq RIP(%rsp),%rsi # esi points at end of src region
+ # Acquire interrupted rsp which was saved-on-stack. This points to
+ # the end of dst region. Note that it is not necessarily current rsp
+ # plus 0xb0, because the second interrupt might align the stack frame.
+ movq RSP(%rsp),%rdi # edi points at end of dst region
+
+ cmpq $restore_end,%rax
+ jae 13f
+
+ # If interrupted rip is before restore_end
+ # then rax hasn't been restored yet
+ movq (%rdi),%rax
+ movq %rax, RAX(%rsp) # save rax
+ addq $RSP_OFFSET,%rdi
+
+ # Set up the copy
+13: movq $RIP,%rcx
+ shr $3,%rcx # convert bytes into count of 64-bit entities
+15: subq $8,%rsi # pre-decrementing copy loop
+ subq $8,%rdi
+ movq (%rsi),%rax
+ movq %rax,(%rdi)
+ loop 15b
+16: movq %rdi,%rsp # final rdi is top of merged stack
+ andb $KERNEL_CS_MASK,CS(%rsp) # CS might have changed
+ jmp 11b
+
+
+
+ENTRY(failsafe_callback)
+ popq %rcx
+ popq %r11
+ iretq
+
+
+ENTRY(coprocessor_error)
+ zeroentry do_coprocessor_error
+
+
+ENTRY(simd_coprocessor_error)
+ zeroentry do_simd_coprocessor_error
+
+
+ENTRY(device_not_available)
+ zeroentry do_device_not_available
+
+
+ENTRY(debug)
+ zeroentry do_debug
+
+
+ENTRY(int3)
+ zeroentry do_int3
+
+ENTRY(overflow)
+ zeroentry do_overflow
+
+
+ENTRY(bounds)
+ zeroentry do_bounds
+
+
+ENTRY(invalid_op)
+ zeroentry do_invalid_op
+
+
+ENTRY(coprocessor_segment_overrun)
+ zeroentry do_coprocessor_segment_overrun
+
+
+ENTRY(invalid_TSS)
+ errorentry do_invalid_TSS
+
+
+ENTRY(segment_not_present)
+ errorentry do_segment_not_present
+
+
+/* runs on exception stack */
+ENTRY(stack_segment)
+ errorentry do_stack_segment
+
+
+ENTRY(general_protection)
+ errorentry do_general_protection
+
+
+ENTRY(alignment_check)
+ errorentry do_alignment_check
+
+
+ENTRY(divide_error)
+ zeroentry do_divide_error
+
+
+ENTRY(spurious_interrupt_bug)
+ zeroentry do_spurious_interrupt_bug
+
+
+ENTRY(page_fault)
+ errorentry do_page_fault
+
+
+
+
+
+ENTRY(thread_starter)
+ popq %rdi
+ popq %rbx
+ pushq $0
+ xorq %rbp,%rbp
+ call *%rbx
+ call exit_thread
+
+
+ENTRY(__arch_switch_threads)
+ pushq %rbp
+ pushq %rbx
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ movq %rsp, (%rdi) /* save ESP */
+ movq (%rsi), %rsp /* restore ESP */
+ movq $1f, 8(%rdi) /* save EIP */
+ pushq 8(%rsi) /* restore EIP */
+ ret
+1:
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ popq %rbx
+ popq %rbp
+ ret
--- /dev/null
+/* Minimal block driver for Mini-OS.
+ * Copyright (c) 2007-2008 Samuel Thibault.
+ * Based on netfront.c.
+ */
+
+#include <stdint.h>
+#include <mini-os/os.h>
+#include <mini-os/xenbus.h>
+#include <mini-os/events.h>
+#include <errno.h>
+#include <xen/io/blkif.h>
+#include <xen/io/protocols.h>
+#include <mini-os/gnttab.h>
+#include <mini-os/xmalloc.h>
+#include <time.h>
+#include <mini-os/blkfront.h>
+#include <mini-os/lib.h>
+#include <fcntl.h>
+
+#ifndef HAVE_LIBC
+#define strtoul simple_strtoul
+#endif
+
+/* Note: we generally don't need to disable IRQs since we hardly do anything in
+ * the interrupt handler. */
+
+/* Note: we really suppose non-preemptive threads. */
+
+DECLARE_WAIT_QUEUE_HEAD(blkfront_queue);
+
+
+
+
+#define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE)
+#define GRANT_INVALID_REF 0
+
+
+struct blk_buffer {
+ void* page;
+ grant_ref_t gref;
+};
+
+struct blkfront_dev {
+ domid_t dom;
+
+ struct blkif_front_ring ring;
+ grant_ref_t ring_ref;
+ evtchn_port_t evtchn;
+ blkif_vdev_t handle;
+
+ char *nodename;
+ char *backend;
+ struct blkfront_info info;
+
+ xenbus_event_queue events;
+
+#ifdef HAVE_LIBC
+ int fd;
+#endif
+};
+
+void blkfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+#ifdef HAVE_LIBC
+ struct blkfront_dev *dev = data;
+ int fd = dev->fd;
+
+ if (fd != -1)
+ files[fd].read = 1;
+#endif
+ wake_up(&blkfront_queue);
+}
+
+static void free_blkfront(struct blkfront_dev *dev)
+{
+ mask_evtchn(dev->evtchn);
+
+ free(dev->backend);
+
+ gnttab_end_access(dev->ring_ref);
+ free_page(dev->ring.sring);
+
+ unbind_evtchn(dev->evtchn);
+
+ free(dev->nodename);
+ free(dev);
+}
+
+struct blkfront_dev *init_blkfront(char *_nodename, struct blkfront_info *info)
+{
+ xenbus_transaction_t xbt;
+ char* err;
+ char* message=NULL;
+ struct blkif_sring *s;
+ int retry=0;
+ char* msg = NULL;
+ char* c;
+ char* nodename = _nodename ? _nodename : "device/vbd/768";
+
+ struct blkfront_dev *dev;
+
+ char path[strlen(nodename) + strlen("/backend-id") + 1];
+
+ printk("******************* BLKFRONT for %s **********\n\n\n", nodename);
+
+ dev = malloc(sizeof(*dev));
+ memset(dev, 0, sizeof(*dev));
+ dev->nodename = strdup(nodename);
+#ifdef HAVE_LIBC
+ dev->fd = -1;
+#endif
+
+ snprintf(path, sizeof(path), "%s/backend-id", nodename);
+ dev->dom = xenbus_read_integer(path);
+ evtchn_alloc_unbound(dev->dom, blkfront_handler, dev, &dev->evtchn);
+
+ s = (struct blkif_sring*) alloc_page();
+ memset(s,0,PAGE_SIZE);
+
+
+ SHARED_RING_INIT(s);
+ FRONT_RING_INIT(&dev->ring, s, PAGE_SIZE);
+
+ dev->ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(s),0);
+
+ dev->events = NULL;
+
+again:
+ err = xenbus_transaction_start(&xbt);
+ if (err) {
+ printk("starting transaction\n");
+ free(err);
+ }
+
+ err = xenbus_printf(xbt, nodename, "ring-ref","%u",
+ dev->ring_ref);
+ if (err) {
+ message = "writing ring-ref";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(xbt, nodename,
+ "event-channel", "%u", dev->evtchn);
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(xbt, nodename,
+ "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE);
+ if (err) {
+ message = "writing protocol";
+ goto abort_transaction;
+ }
+
+ snprintf(path, sizeof(path), "%s/state", nodename);
+ err = xenbus_switch_state(xbt, path, XenbusStateConnected);
+ if (err) {
+ message = "switching state";
+ goto abort_transaction;
+ }
+
+
+ err = xenbus_transaction_end(xbt, 0, &retry);
+ free(err);
+ if (retry) {
+ goto again;
+ printk("completing transaction\n");
+ }
+
+ goto done;
+
+abort_transaction:
+ free(err);
+ err = xenbus_transaction_end(xbt, 1, &retry);
+ printk("Abort transaction %s\n", message);
+ goto error;
+
+done:
+
+ snprintf(path, sizeof(path), "%s/backend", nodename);
+ msg = xenbus_read(XBT_NIL, path, &dev->backend);
+ if (msg) {
+ printk("Error %s when reading the backend path %s\n", msg, path);
+ goto error;
+ }
+
+ printk("backend at %s\n", dev->backend);
+
+ dev->handle = strtoul(strrchr(nodename, '/')+1, NULL, 0);
+
+ {
+ XenbusState state;
+ char path[strlen(dev->backend) + strlen("/feature-flush-cache") + 1];
+ snprintf(path, sizeof(path), "%s/mode", dev->backend);
+ msg = xenbus_read(XBT_NIL, path, &c);
+ if (msg) {
+ printk("Error %s when reading the mode\n", msg);
+ goto error;
+ }
+ if (*c == 'w')
+ dev->info.mode = O_RDWR;
+ else
+ dev->info.mode = O_RDONLY;
+ free(c);
+
+ snprintf(path, sizeof(path), "%s/state", dev->backend);
+
+ xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
+
+ msg = NULL;
+ state = xenbus_read_integer(path);
+ while (msg == NULL && state < XenbusStateConnected)
+ msg = xenbus_wait_for_state_change(path, &state, &dev->events);
+ if (msg != NULL || state != XenbusStateConnected) {
+ printk("backend not available, state=%d\n", state);
+ xenbus_unwatch_path_token(XBT_NIL, path, path);
+ goto error;
+ }
+
+ snprintf(path, sizeof(path), "%s/info", dev->backend);
+ dev->info.info = xenbus_read_integer(path);
+
+ snprintf(path, sizeof(path), "%s/sectors", dev->backend);
+ // FIXME: read_integer returns an int, so disk size limited to 1TB for now
+ dev->info.sectors = xenbus_read_integer(path);
+
+ snprintf(path, sizeof(path), "%s/sector-size", dev->backend);
+ dev->info.sector_size = xenbus_read_integer(path);
+
+ snprintf(path, sizeof(path), "%s/feature-barrier", dev->backend);
+ dev->info.barrier = xenbus_read_integer(path);
+
+ snprintf(path, sizeof(path), "%s/feature-flush-cache", dev->backend);
+ dev->info.flush = xenbus_read_integer(path);
+
+ *info = dev->info;
+ }
+ unmask_evtchn(dev->evtchn);
+
+ printk("%u sectors of %u bytes\n", dev->info.sectors, dev->info.sector_size);
+ printk("**************************\n");
+
+ return dev;
+
+error:
+ free(msg);
+ free(err);
+ free_blkfront(dev);
+ return NULL;
+}
+
+void shutdown_blkfront(struct blkfront_dev *dev)
+{
+ char* err = NULL, *err2;
+ XenbusState state;
+
+ char path[strlen(dev->backend) + strlen("/state") + 1];
+ char nodename[strlen(dev->nodename) + strlen("/event-channel") + 1];
+
+ blkfront_sync(dev);
+
+ printk("close blk: backend=%s node=%s\n", dev->backend, dev->nodename);
+
+ snprintf(path, sizeof(path), "%s/state", dev->backend);
+ snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
+ printk("shutdown_blkfront: error changing state to %d: %s\n",
+ XenbusStateClosing, err);
+ goto close;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateClosing)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ free(err);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
+ printk("shutdown_blkfront: error changing state to %d: %s\n",
+ XenbusStateClosed, err);
+ goto close;
+ }
+ state = xenbus_read_integer(path);
+ while (state < XenbusStateClosed) {
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ free(err);
+ }
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
+ printk("shutdown_blkfront: error changing state to %d: %s\n",
+ XenbusStateInitialising, err);
+ goto close;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+
+close:
+ free(err);
+ err2 = xenbus_unwatch_path_token(XBT_NIL, path, path);
+ free(err2);
+
+ snprintf(nodename, sizeof(nodename), "%s/ring-ref", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+ snprintf(nodename, sizeof(nodename), "%s/event-channel", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+
+ if (!err)
+ free_blkfront(dev);
+}
+
+static void blkfront_wait_slot(struct blkfront_dev *dev)
+{
+ /* Wait for a slot */
+ if (RING_FULL(&dev->ring)) {
+ unsigned long flags;
+ DEFINE_WAIT(w);
+ local_irq_save(flags);
+ while (1) {
+ blkfront_aio_poll(dev);
+ if (!RING_FULL(&dev->ring))
+ break;
+ /* Really no slot, go to sleep. */
+ add_waiter(w, blkfront_queue);
+ local_irq_restore(flags);
+ schedule();
+ local_irq_save(flags);
+ }
+ remove_waiter(w, blkfront_queue);
+ local_irq_restore(flags);
+ }
+}
+
+/* Issue an aio */
+void blkfront_aio(struct blkfront_aiocb *aiocbp, int write)
+{
+ struct blkfront_dev *dev = aiocbp->aio_dev;
+ struct blkif_request *req;
+ RING_IDX i;
+ int notify;
+ int n, j;
+ uintptr_t start, end;
+
+ // Can't io at non-sector-aligned location
+ ASSERT(!(aiocbp->aio_offset & (dev->info.sector_size-1)));
+ // Can't io non-sector-sized amounts
+ ASSERT(!(aiocbp->aio_nbytes & (dev->info.sector_size-1)));
+ // Can't io non-sector-aligned buffer
+ ASSERT(!((uintptr_t) aiocbp->aio_buf & (dev->info.sector_size-1)));
+
+ start = (uintptr_t)aiocbp->aio_buf & PAGE_MASK;
+ end = ((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes + PAGE_SIZE - 1) & PAGE_MASK;
+ aiocbp->n = n = (end - start) / PAGE_SIZE;
+
+ /* qemu's IDE max multsect is 16 (8KB) and SCSI max DMA was set to 32KB,
+ * so max 44KB can't happen */
+ ASSERT(n <= BLKIF_MAX_SEGMENTS_PER_REQUEST);
+
+ blkfront_wait_slot(dev);
+ i = dev->ring.req_prod_pvt;
+ req = RING_GET_REQUEST(&dev->ring, i);
+
+ req->operation = write ? BLKIF_OP_WRITE : BLKIF_OP_READ;
+ req->nr_segments = n;
+ req->handle = dev->handle;
+ req->id = (uintptr_t) aiocbp;
+ req->sector_number = aiocbp->aio_offset / 512;
+
+ for (j = 0; j < n; j++) {
+ req->seg[j].first_sect = 0;
+ req->seg[j].last_sect = PAGE_SIZE / 512 - 1;
+ }
+ req->seg[0].first_sect = ((uintptr_t)aiocbp->aio_buf & ~PAGE_MASK) / 512;
+ req->seg[n-1].last_sect = (((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes - 1) & ~PAGE_MASK) / 512;
+ for (j = 0; j < n; j++) {
+ uintptr_t data = start + j * PAGE_SIZE;
+ if (!write) {
+ /* Trigger CoW if needed */
+ *(char*)(data + (req->seg[j].first_sect << 9)) = 0;
+ barrier();
+ }
+ aiocbp->gref[j] = req->seg[j].gref =
+ gnttab_grant_access(dev->dom, virtual_to_mfn(data), write);
+ }
+
+ dev->ring.req_prod_pvt = i + 1;
+
+ wmb();
+ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify);
+
+ if(notify) notify_remote_via_evtchn(dev->evtchn);
+}
+
+static void blkfront_aio_cb(struct blkfront_aiocb *aiocbp, int ret)
+{
+ aiocbp->data = (void*) 1;
+ aiocbp->aio_cb = NULL;
+}
+
+void blkfront_io(struct blkfront_aiocb *aiocbp, int write)
+{
+ unsigned long flags;
+ DEFINE_WAIT(w);
+
+ ASSERT(!aiocbp->aio_cb);
+ aiocbp->aio_cb = blkfront_aio_cb;
+ blkfront_aio(aiocbp, write);
+ aiocbp->data = NULL;
+
+ local_irq_save(flags);
+ while (1) {
+ blkfront_aio_poll(aiocbp->aio_dev);
+ if (aiocbp->data)
+ break;
+
+ add_waiter(w, blkfront_queue);
+ local_irq_restore(flags);
+ schedule();
+ local_irq_save(flags);
+ }
+ remove_waiter(w, blkfront_queue);
+ local_irq_restore(flags);
+}
+
+static void blkfront_push_operation(struct blkfront_dev *dev, uint8_t op, uint64_t id)
+{
+ int i;
+ struct blkif_request *req;
+ int notify;
+
+ blkfront_wait_slot(dev);
+ i = dev->ring.req_prod_pvt;
+ req = RING_GET_REQUEST(&dev->ring, i);
+ req->operation = op;
+ req->nr_segments = 0;
+ req->handle = dev->handle;
+ req->id = id;
+ /* Not needed anyway, but the backend will check it */
+ req->sector_number = 0;
+ dev->ring.req_prod_pvt = i + 1;
+ wmb();
+ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify);
+ if (notify) notify_remote_via_evtchn(dev->evtchn);
+}
+
+void blkfront_aio_push_operation(struct blkfront_aiocb *aiocbp, uint8_t op)
+{
+ struct blkfront_dev *dev = aiocbp->aio_dev;
+ blkfront_push_operation(dev, op, (uintptr_t) aiocbp);
+}
+
+void blkfront_sync(struct blkfront_dev *dev)
+{
+ unsigned long flags;
+ DEFINE_WAIT(w);
+
+ if (dev->info.mode == O_RDWR) {
+ if (dev->info.barrier == 1)
+ blkfront_push_operation(dev, BLKIF_OP_WRITE_BARRIER, 0);
+
+ if (dev->info.flush == 1)
+ blkfront_push_operation(dev, BLKIF_OP_FLUSH_DISKCACHE, 0);
+ }
+
+ /* Note: This won't finish if another thread enqueues requests. */
+ local_irq_save(flags);
+ while (1) {
+ blkfront_aio_poll(dev);
+ if (RING_FREE_REQUESTS(&dev->ring) == RING_SIZE(&dev->ring))
+ break;
+
+ add_waiter(w, blkfront_queue);
+ local_irq_restore(flags);
+ schedule();
+ local_irq_save(flags);
+ }
+ remove_waiter(w, blkfront_queue);
+ local_irq_restore(flags);
+}
+
+int blkfront_aio_poll(struct blkfront_dev *dev)
+{
+ RING_IDX rp, cons;
+ struct blkif_response *rsp;
+ int more;
+ int nr_consumed;
+
+moretodo:
+#ifdef HAVE_LIBC
+ if (dev->fd != -1) {
+ files[dev->fd].read = 0;
+ mb(); /* Make sure to let the handler set read to 1 before we start looking at the ring */
+ }
+#endif
+
+ rp = dev->ring.sring->rsp_prod;
+ rmb(); /* Ensure we see queued responses up to 'rp'. */
+ cons = dev->ring.rsp_cons;
+
+ nr_consumed = 0;
+ while ((cons != rp))
+ {
+ struct blkfront_aiocb *aiocbp;
+ int status;
+
+ rsp = RING_GET_RESPONSE(&dev->ring, cons);
+ nr_consumed++;
+
+ aiocbp = (void*) (uintptr_t) rsp->id;
+ status = rsp->status;
+
+ switch (rsp->operation) {
+ case BLKIF_OP_READ:
+ case BLKIF_OP_WRITE:
+ {
+ int j;
+
+ if (status != BLKIF_RSP_OKAY)
+ printk("%s error %d on %s at offset %llu, num bytes %llu\n",
+ rsp->operation == BLKIF_OP_READ?"read":"write",
+ status, aiocbp->aio_dev->nodename,
+ (unsigned long long) aiocbp->aio_offset,
+ (unsigned long long) aiocbp->aio_nbytes);
+
+ for (j = 0; j < aiocbp->n; j++)
+ gnttab_end_access(aiocbp->gref[j]);
+
+ break;
+ }
+
+ case BLKIF_OP_WRITE_BARRIER:
+ if (status != BLKIF_RSP_OKAY)
+ printk("write barrier error %d\n", status);
+ break;
+ case BLKIF_OP_FLUSH_DISKCACHE:
+ if (status != BLKIF_RSP_OKAY)
+ printk("flush error %d\n", status);
+ break;
+
+ default:
+ printk("unrecognized block operation %d response (status %d)\n", rsp->operation, status);
+ break;
+ }
+
+ dev->ring.rsp_cons = ++cons;
+ /* Nota: callback frees aiocbp itself */
+ if (aiocbp && aiocbp->aio_cb)
+ aiocbp->aio_cb(aiocbp, status ? -EIO : 0);
+ if (dev->ring.rsp_cons != cons)
+ /* We reentered, we must not continue here */
+ break;
+ }
+
+ RING_FINAL_CHECK_FOR_RESPONSES(&dev->ring, more);
+ if (more) goto moretodo;
+
+ return nr_consumed;
+}
+
+#ifdef HAVE_LIBC
+int blkfront_open(struct blkfront_dev *dev)
+{
+ /* Silently prevent multiple opens */
+ if(dev->fd != -1) {
+ return dev->fd;
+ }
+ dev->fd = alloc_fd(FTYPE_BLK);
+ printk("blk_open(%s) -> %d\n", dev->nodename, dev->fd);
+ files[dev->fd].blk.dev = dev;
+ files[dev->fd].blk.offset = 0;
+ return dev->fd;
+}
+
+int blkfront_posix_rwop(int fd, uint8_t* buf, size_t count, int write)
+{
+ struct blkfront_dev* dev = files[fd].blk.dev;
+ off_t offset = files[fd].blk.offset;
+ struct blkfront_aiocb aiocb;
+ unsigned long long disksize = dev->info.sectors * dev->info.sector_size;
+ unsigned int blocksize = dev->info.sector_size;
+
+ int blknum;
+ int blkoff;
+ size_t bytes;
+ int rc = 0;
+ int alignedbuf = 0;
+ uint8_t* copybuf = NULL;
+
+ /* RW 0 bytes is just a NOP */
+ if(count == 0) {
+ return 0;
+ }
+ /* Check for NULL buffer */
+ if( buf == NULL ) {
+ errno = EFAULT;
+ return -1;
+ }
+
+ /* Write mode checks */
+ if(write) {
+ /*Make sure we have write permission */
+ if(dev->info.info & VDISK_READONLY
+ || (dev->info.mode != O_RDWR && dev->info.mode != O_WRONLY)) {
+ errno = EACCES;
+ return -1;
+ }
+ /*Make sure disk is big enough for this write */
+ if(offset + count > disksize) {
+ errno = ENOSPC;
+ return -1;
+ }
+ }
+ /* Read mode checks */
+ else
+ {
+ /* Reading past the disk? Just return 0 */
+ if(offset >= disksize) {
+ return 0;
+ }
+
+ /*If the requested read is bigger than the disk, just
+ * read as much as we can until the end */
+ if(offset + count > disksize) {
+ count = disksize - offset;
+ }
+ }
+ /* Determine which block to start at and at which offset inside of it */
+ blknum = offset / blocksize;
+ blkoff = offset % blocksize;
+
+ /* Optimization: We need to check if buf is aligned to the sector size.
+ * This is somewhat tricky code. We have to add the blocksize - block offset
+ * because the first block may be a partial block and then for every subsequent
+ * block rw the buffer will be offset.*/
+ if(!((uintptr_t) (buf +(blocksize - blkoff)) & (dev->info.sector_size-1))) {
+ alignedbuf = 1;
+ }
+
+ /* Setup aiocb block object */
+ aiocb.aio_dev = dev;
+ aiocb.aio_offset = blknum * blocksize;
+ aiocb.aio_cb = NULL;
+ aiocb.data = NULL;
+
+ /* If our buffer is unaligned or its aligned but we will need to rw a partial block
+ * then a copy will have to be done */
+ if(!alignedbuf || blkoff != 0 || count % blocksize != 0) {
+ copybuf = _xmalloc(blocksize, dev->info.sector_size);
+ }
+
+ rc = count;
+ while(count > 0) {
+ /* determine how many bytes to read/write from/to the current block buffer */
+ if(!alignedbuf || blkoff != 0 || count < blocksize) {
+ /* This is the case for unaligned R/W or partial block */
+ bytes = count < blocksize - blkoff ? count : blocksize - blkoff;
+ aiocb.aio_nbytes = blocksize;
+ } else {
+ /* We can optimize further if buffer is page aligned */
+ int not_page_aligned = 0;
+ if(((uintptr_t)buf) & (PAGE_SIZE -1)) {
+ not_page_aligned = 1;
+ }
+
+ /* For an aligned R/W we can read up to the maximum transfer size */
+ bytes = count > (BLKIF_MAX_SEGMENTS_PER_REQUEST-not_page_aligned)*PAGE_SIZE
+ ? (BLKIF_MAX_SEGMENTS_PER_REQUEST-not_page_aligned)*PAGE_SIZE
+ : count & ~(blocksize -1);
+ aiocb.aio_nbytes = bytes;
+ }
+
+ /* read operation */
+ if(!write) {
+ if (alignedbuf && bytes >= blocksize) {
+ /* If aligned and were reading a whole block, just read right into buf */
+ aiocb.aio_buf = buf;
+ blkfront_read(&aiocb);
+ } else {
+ /* If not then we have to do a copy */
+ aiocb.aio_buf = copybuf;
+ blkfront_read(&aiocb);
+ memcpy(buf, ©buf[blkoff], bytes);
+ }
+ }
+ /* Write operation */
+ else {
+ if(alignedbuf && bytes >= blocksize) {
+ /* If aligned and were writing a whole block, just write directly from buf */
+ aiocb.aio_buf = buf;
+ blkfront_write(&aiocb);
+ } else {
+ /* If not then we have to do a copy. */
+ aiocb.aio_buf = copybuf;
+ /* If we're writing a partial block, we need to read the current contents first
+ * so we don't overwrite the extra bits with garbage */
+ if(blkoff != 0 || bytes < blocksize) {
+ blkfront_read(&aiocb);
+ }
+ memcpy(©buf[blkoff], buf, bytes);
+ blkfront_write(&aiocb);
+ }
+ }
+ /* Will start at beginning of all remaining blocks */
+ blkoff = 0;
+
+ /* Increment counters and continue */
+ count -= bytes;
+ buf += bytes;
+ if(bytes < blocksize) {
+ //At minimum we read one block
+ aiocb.aio_offset += blocksize;
+ } else {
+ //If we read more than a block, was a multiple of blocksize
+ aiocb.aio_offset += bytes;
+ }
+ }
+
+ free(copybuf);
+ files[fd].blk.offset += rc;
+ return rc;
+
+}
+
+int blkfront_posix_fstat(int fd, struct stat* buf)
+{
+ struct blkfront_dev* dev = files[fd].blk.dev;
+
+ buf->st_mode = dev->info.mode;
+ buf->st_uid = 0;
+ buf->st_gid = 0;
+ buf->st_size = dev->info.sectors * dev->info.sector_size;
+ buf->st_atime = buf->st_mtime = buf->st_ctime = time(NULL);
+
+ return 0;
+}
+#endif
--- /dev/null
+include $(MINI-OS_ROOT)/config/StdGNU.mk
+include $(MINI-OS_ROOT)/Config.mk
+CFLAGS += $(DEF_CFLAGS) $(ARCH_CFLAGS)
+CPPFLAGS += $(DEF_CPPFLAGS) $(ARCH_CPPFLAGS) $(extra_incl)
+ASFLAGS += $(DEF_ASFLAGS) $(ARCH_ASFLAGS)
+LDFLAGS += $(DEF_LDFLAGS) $(ARCH_LDFLAGS)
+
+# Override settings for this OS
+PTHREAD_LIBS =
+nosharedlibs=y
--- /dev/null
+AS = $(CROSS_COMPILE)as
+LD = $(CROSS_COMPILE)ld
+ifeq ($(clang),y)
+CC = $(CROSS_COMPILE)clang
+LD_LTO = $(CROSS_COMPILE)llvm-ld
+else
+CC = $(CROSS_COMPILE)gcc
+LD_LTO = $(CROSS_COMPILE)ld
+endif
+CPP = $(CC) -E
+AR = $(CROSS_COMPILE)ar
+RANLIB = $(CROSS_COMPILE)ranlib
+NM = $(CROSS_COMPILE)nm
+STRIP = $(CROSS_COMPILE)strip
+OBJCOPY = $(CROSS_COMPILE)objcopy
+OBJDUMP = $(CROSS_COMPILE)objdump
+SIZEUTIL = $(CROSS_COMPILE)size
+
+# Allow git to be wrappered in the environment
+GIT ?= git
+
+INSTALL = install
+INSTALL_DIR = $(INSTALL) -d -m0755 -p
+INSTALL_DATA = $(INSTALL) -m0644 -p
+INSTALL_PROG = $(INSTALL) -m0755 -p
+
+BOOT_DIR ?= /boot
+
+SOCKET_LIBS =
+UTIL_LIBS = -lutil
+DLOPEN_LIBS = -ldl
+
+SONAME_LDFLAG = -soname
+SHLIB_LDFLAGS = -shared
+
+ifneq ($(debug),y)
+CFLAGS += -O2 -fomit-frame-pointer
+else
+# Less than -O1 produces bad code and large stack frames
+CFLAGS += -O1 -fno-omit-frame-pointer
+CFLAGS-$(gcc) += -fno-optimize-sibling-calls
+endif
+
+ifeq ($(lto),y)
+CFLAGS += -flto
+LDFLAGS-$(clang) += -plugin LLVMgold.so
+endif
--- /dev/null
+CONFIG_ARM := y
+CONFIG_ARM_32 := y
+CONFIG_ARM_$(XEN_OS) := y
+
+CONFIG_XEN_INSTALL_SUFFIX :=
+
+# -march= -mcpu=
+
+# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
+CFLAGS += -marm
+
+HAS_PL011 := y
+HAS_EXYNOS4210 := y
+HAS_OMAP := y
+HAS_NS16550 := y
+
+# Use only if calling $(LD) directly.
+LDFLAGS_DIRECT += -EL
+
+CONFIG_LOAD_ADDRESS ?= 0x80000000
+
+IOEMU_CPU_ARCH ?= arm
--- /dev/null
+CONFIG_ARM := y
+CONFIG_ARM_64 := y
+CONFIG_ARM_$(XEN_OS) := y
+
+CONFIG_XEN_INSTALL_SUFFIX :=
+
+CFLAGS += #-marm -march= -mcpu= etc
+
+HAS_PL011 := y
+HAS_NS16550 := y
+
+# Use only if calling $(LD) directly.
+LDFLAGS_DIRECT += -EL
+
+CONFIG_LOAD_ADDRESS ?= 0x80000000
+
+IOEMU_CPU_ARCH ?= aarch64
+
+EFI_DIR ?= /usr/lib64/efi
--- /dev/null
+CONFIG_X86 := y
+CONFIG_X86_32 := y
+CONFIG_X86_$(XEN_OS) := y
+
+CONFIG_HVM := y
+CONFIG_MIGRATE := y
+CONFIG_XCUTILS := y
+
+HAS_MEM_ACCESS := y
+HAS_MEM_PAGING := y
+HAS_MEM_SHARING := y
+
+CFLAGS += -m32 -march=i686
+
+# Use only if calling $(LD) directly.
+LDFLAGS_DIRECT_OpenBSD = _obsd
+LDFLAGS_DIRECT_FreeBSD = _fbsd
+LDFLAGS_DIRECT += -melf_i386$(LDFLAGS_DIRECT_$(XEN_OS))
+
+IOEMU_CPU_ARCH ?= i386
--- /dev/null
+CONFIG_X86 := y
+CONFIG_X86_64 := y
+CONFIG_X86_$(XEN_OS) := y
+
+CONFIG_COMPAT := y
+CONFIG_HVM := y
+CONFIG_MIGRATE := y
+CONFIG_XCUTILS := y
+
+HAS_MEM_ACCESS := y
+HAS_MEM_PAGING := y
+HAS_MEM_SHARING := y
+
+CONFIG_XEN_INSTALL_SUFFIX := .gz
+
+CFLAGS += -m64
+
+SunOS_LIBDIR = $(SunOS_LIBDIR_x86_64)
+
+EFI_DIR ?= /usr/lib64/efi
+
+# Use only if calling $(LD) directly.
+ifeq ($(XEN_OS),OpenBSD)
+LDFLAGS_DIRECT += -melf_x86_64_obsd
+else
+ifeq ($(XEN_OS),FreeBSD)
+LDFLAGS_DIRECT += -melf_x86_64_fbsd
+else
+LDFLAGS_DIRECT += -melf_x86_64
+endif
+endif
+
+IOEMU_CPU_ARCH ?= x86_64
--- /dev/null
+/*
+ ****************************************************************************
+ * (C) 2006 - Grzegorz Milos - Cambridge University
+ ****************************************************************************
+ *
+ * File: console.h
+ * Author: Grzegorz Milos
+ * Changes:
+ *
+ * Date: Mar 2006
+ *
+ * Environment: Xen Minimal OS
+ * Description: Console interface.
+ *
+ * Handles console I/O. Defines printk.
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <mini-os/types.h>
+#include <mini-os/wait.h>
+#include <mini-os/mm.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/events.h>
+#include <mini-os/os.h>
+#include <mini-os/lib.h>
+#include <mini-os/xenbus.h>
+#include <xen/io/console.h>
+
+
+/* Copies all print output to the Xen emergency console apart
+ of standard dom0 handled console */
+#define USE_XEN_CONSOLE
+
+
+/* If console not initialised the printk will be sent to xen serial line
+ NOTE: you need to enable verbose in xen/Rules.mk for it to work. */
+static int console_initialised = 0;
+
+__attribute__((weak)) void console_input(char * buf, unsigned len)
+{
+ if(len > 0)
+ {
+ /* Just repeat what's written */
+ buf[len] = '\0';
+ printk("%s", buf);
+
+ if(buf[len-1] == '\r')
+ printk("\nNo console input handler.\n");
+ }
+}
+
+#ifndef HAVE_LIBC
+void xencons_rx(char *buf, unsigned len, struct pt_regs *regs)
+{
+ console_input(buf, len);
+}
+
+void xencons_tx(void)
+{
+ /* Do nothing, handled by _rx */
+}
+#endif
+
+
+void console_print(struct consfront_dev *dev, char *data, int length)
+{
+ char *curr_char, saved_char;
+ char copied_str[length+1];
+ char *copied_ptr;
+ int part_len;
+ int (*ring_send_fn)(struct consfront_dev *dev, const char *data, unsigned length);
+
+ if(!console_initialised)
+ ring_send_fn = xencons_ring_send_no_notify;
+ else
+ ring_send_fn = xencons_ring_send;
+
+ copied_ptr = copied_str;
+ memcpy(copied_ptr, data, length);
+ for(curr_char = copied_ptr; curr_char < copied_ptr+length-1; curr_char++)
+ {
+ if(*curr_char == '\n')
+ {
+ *curr_char = '\r';
+ saved_char = *(curr_char+1);
+ *(curr_char+1) = '\n';
+ part_len = curr_char - copied_ptr + 2;
+ ring_send_fn(dev, copied_ptr, part_len);
+ *(curr_char+1) = saved_char;
+ copied_ptr = curr_char+1;
+ length -= part_len - 1;
+ }
+ }
+
+ if (copied_ptr[length-1] == '\n') {
+ copied_ptr[length-1] = '\r';
+ copied_ptr[length] = '\n';
+ length++;
+ }
+
+ ring_send_fn(dev, copied_ptr, length);
+}
+
+void print(int direct, const char *fmt, va_list args)
+{
+ static char buf[1024];
+
+ (void)vsnprintf(buf, sizeof(buf), fmt, args);
+
+ if(direct)
+ {
+ (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
+ return;
+ } else {
+#ifndef USE_XEN_CONSOLE
+ if(!console_initialised)
+#endif
+ (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
+
+ console_print(NULL, buf, strlen(buf));
+ }
+}
+
+void printk(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ print(0, fmt, args);
+ va_end(args);
+}
+
+void xprintk(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ print(1, fmt, args);
+ va_end(args);
+}
+void init_console(void)
+{
+ printk("Initialising console ... ");
+ xencons_ring_init();
+ console_initialised = 1;
+ /* This is also required to notify the daemon */
+ printk("done.\n");
+}
--- /dev/null
+
+void console_handle_input(evtchn_port_t port, struct pt_regs *regs, void *data);
--- /dev/null
+#include <mini-os/types.h>
+#include <mini-os/wait.h>
+#include <mini-os/mm.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/events.h>
+#include <mini-os/os.h>
+#include <mini-os/lib.h>
+#include <mini-os/xenbus.h>
+#include <xen/io/console.h>
+#include <xen/io/protocols.h>
+#include <xen/io/ring.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/gnttab.h>
+#include "console.h"
+
+void free_consfront(struct consfront_dev *dev)
+{
+ char* err = NULL;
+ XenbusState state;
+
+ char path[strlen(dev->backend) + strlen("/state") + 1];
+ char nodename[strlen(dev->nodename) + strlen("/state") + 1];
+
+ snprintf(path, sizeof(path), "%s/state", dev->backend);
+ snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
+ printk("free_consfront: error changing state to %d: %s\n",
+ XenbusStateClosing, err);
+ goto close;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateClosing)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ free(err);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
+ printk("free_consfront: error changing state to %d: %s\n",
+ XenbusStateClosed, err);
+ goto close;
+ }
+
+close:
+ free(err);
+ err = xenbus_unwatch_path_token(XBT_NIL, path, path);
+ free(err);
+
+ mask_evtchn(dev->evtchn);
+ unbind_evtchn(dev->evtchn);
+ free(dev->backend);
+ free(dev->nodename);
+
+ gnttab_end_access(dev->ring_ref);
+
+ free_page(dev->ring);
+ free(dev);
+}
+
+struct consfront_dev *init_consfront(char *_nodename)
+{
+ xenbus_transaction_t xbt;
+ char* err = NULL;
+ char* message=NULL;
+ int retry=0;
+ char* msg = NULL;
+ char nodename[256];
+ char path[256];
+ static int consfrontends = 3;
+ struct consfront_dev *dev;
+ int res;
+
+ if (!_nodename)
+ snprintf(nodename, sizeof(nodename), "device/console/%d", consfrontends);
+ else {
+ strncpy(nodename, _nodename, sizeof(nodename) - 1);
+ nodename[sizeof(nodename) - 1] = 0;
+ }
+
+ printk("******************* CONSFRONT for %s **********\n\n\n", nodename);
+
+ consfrontends++;
+ dev = malloc(sizeof(*dev));
+ memset(dev, 0, sizeof(*dev));
+ dev->nodename = strdup(nodename);
+#ifdef HAVE_LIBC
+ dev->fd = -1;
+#endif
+
+ snprintf(path, sizeof(path), "%s/backend-id", nodename);
+ if ((res = xenbus_read_integer(path)) < 0)
+ goto error;
+ else
+ dev->dom = res;
+ evtchn_alloc_unbound(dev->dom, console_handle_input, dev, &dev->evtchn);
+
+ dev->ring = (struct xencons_interface *) alloc_page();
+ memset(dev->ring, 0, PAGE_SIZE);
+ dev->ring_ref = gnttab_grant_access(dev->dom, virt_to_mfn(dev->ring), 0);
+
+ dev->events = NULL;
+
+again:
+ err = xenbus_transaction_start(&xbt);
+ if (err) {
+ printk("starting transaction\n");
+ free(err);
+ }
+
+ err = xenbus_printf(xbt, nodename, "ring-ref","%u",
+ dev->ring_ref);
+ if (err) {
+ message = "writing ring-ref";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(xbt, nodename,
+ "port", "%u", dev->evtchn);
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(xbt, nodename,
+ "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE);
+ if (err) {
+ message = "writing protocol";
+ goto abort_transaction;
+ }
+
+ snprintf(path, sizeof(path), "%s/state", nodename);
+ err = xenbus_switch_state(xbt, path, XenbusStateConnected);
+ if (err) {
+ message = "switching state";
+ goto abort_transaction;
+ }
+
+
+ err = xenbus_transaction_end(xbt, 0, &retry);
+ free(err);
+ if (retry) {
+ goto again;
+ printk("completing transaction\n");
+ }
+
+ goto done;
+
+abort_transaction:
+ free(err);
+ err = xenbus_transaction_end(xbt, 1, &retry);
+ printk("Abort transaction %s\n", message);
+ goto error;
+
+done:
+
+ snprintf(path, sizeof(path), "%s/backend", nodename);
+ msg = xenbus_read(XBT_NIL, path, &dev->backend);
+ if (msg) {
+ printk("Error %s when reading the backend path %s\n", msg, path);
+ goto error;
+ }
+
+ printk("backend at %s\n", dev->backend);
+
+ {
+ XenbusState state;
+ char path[strlen(dev->backend) + strlen("/state") + 1];
+ snprintf(path, sizeof(path), "%s/state", dev->backend);
+
+ xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
+ msg = NULL;
+ state = xenbus_read_integer(path);
+ while (msg == NULL && state < XenbusStateConnected)
+ msg = xenbus_wait_for_state_change(path, &state, &dev->events);
+ if (msg != NULL || state != XenbusStateConnected) {
+ printk("backend not available, state=%d\n", state);
+ err = xenbus_unwatch_path_token(XBT_NIL, path, path);
+ goto error;
+ }
+ }
+ unmask_evtchn(dev->evtchn);
+
+ printk("**************************\n");
+
+ return dev;
+
+error:
+ free(msg);
+ free(err);
+ free_consfront(dev);
+ return NULL;
+}
+
+void fini_console(struct consfront_dev *dev)
+{
+ if (dev) free_consfront(dev);
+}
+
--- /dev/null
+#include <mini-os/types.h>
+#include <mini-os/wait.h>
+#include <mini-os/mm.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/events.h>
+#include <mini-os/os.h>
+#include <mini-os/lib.h>
+#include <mini-os/xenbus.h>
+#include <xen/io/console.h>
+#include <xen/io/protocols.h>
+#include <xen/io/ring.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/gnttab.h>
+#include "console.h"
+
+DECLARE_WAIT_QUEUE_HEAD(console_queue);
+
+static inline void notify_daemon(struct consfront_dev *dev)
+{
+ /* Use evtchn: this is called early, before irq is set up. */
+ if (!dev)
+ notify_remote_via_evtchn(start_info.console.domU.evtchn);
+ else
+ notify_remote_via_evtchn(dev->evtchn);
+}
+
+static inline struct xencons_interface *xencons_interface(void)
+{
+ if (start_info.console.domU.evtchn)
+ return mfn_to_virt(start_info.console.domU.mfn);
+ else
+ return NULL;
+}
+
+int xencons_ring_send_no_notify(struct consfront_dev *dev, const char *data, unsigned len)
+{
+ int sent = 0;
+ struct xencons_interface *intf;
+ XENCONS_RING_IDX cons, prod;
+
+ if (!dev)
+ intf = xencons_interface();
+ else
+ intf = dev->ring;
+ if (!intf)
+ return sent;
+
+ cons = intf->out_cons;
+ prod = intf->out_prod;
+ mb();
+ BUG_ON((prod - cons) > sizeof(intf->out));
+
+ while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
+ intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
+
+ wmb();
+ intf->out_prod = prod;
+
+ return sent;
+}
+
+int xencons_ring_send(struct consfront_dev *dev, const char *data, unsigned len)
+{
+ int sent;
+
+ sent = xencons_ring_send_no_notify(dev, data, len);
+ notify_daemon(dev);
+
+ return sent;
+}
+
+
+
+void console_handle_input(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+ struct consfront_dev *dev = (struct consfront_dev *) data;
+#ifdef HAVE_LIBC
+ int fd = dev ? dev->fd : -1;
+
+ if (fd != -1)
+ files[fd].read = 1;
+
+ wake_up(&console_queue);
+#else
+ struct xencons_interface *intf = xencons_interface();
+ XENCONS_RING_IDX cons, prod;
+
+ cons = intf->in_cons;
+ prod = intf->in_prod;
+ mb();
+ BUG_ON((prod - cons) > sizeof(intf->in));
+
+ while (cons != prod) {
+ xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1, regs);
+ cons++;
+ }
+
+ mb();
+ intf->in_cons = cons;
+
+ notify_daemon(dev);
+
+ xencons_tx();
+#endif
+}
+
+#ifdef HAVE_LIBC
+int xencons_ring_avail(struct consfront_dev *dev)
+{
+ struct xencons_interface *intf;
+ XENCONS_RING_IDX cons, prod;
+
+ if (!dev)
+ intf = xencons_interface();
+ else
+ intf = dev->ring;
+
+ cons = intf->in_cons;
+ prod = intf->in_prod;
+ mb();
+ BUG_ON((prod - cons) > sizeof(intf->in));
+
+ return prod - cons;
+}
+
+int xencons_ring_recv(struct consfront_dev *dev, char *data, unsigned len)
+{
+ struct xencons_interface *intf;
+ XENCONS_RING_IDX cons, prod;
+ unsigned filled = 0;
+
+ if (!dev)
+ intf = xencons_interface();
+ else
+ intf = dev->ring;
+
+ cons = intf->in_cons;
+ prod = intf->in_prod;
+ mb();
+ BUG_ON((prod - cons) > sizeof(intf->in));
+
+ while (filled < len && cons + filled != prod) {
+ data[filled] = *(intf->in + MASK_XENCONS_IDX(cons + filled, intf->in));
+ filled++;
+ }
+
+ mb();
+ intf->in_cons = cons + filled;
+
+ notify_daemon(dev);
+
+ return filled;
+}
+#endif
+
+struct consfront_dev *xencons_ring_init(void)
+{
+ int err;
+ struct consfront_dev *dev;
+
+ if (!start_info.console.domU.evtchn)
+ return 0;
+
+ dev = malloc(sizeof(struct consfront_dev));
+ memset(dev, 0, sizeof(struct consfront_dev));
+ dev->nodename = "device/console";
+ dev->dom = 0;
+ dev->backend = 0;
+ dev->ring_ref = 0;
+
+#ifdef HAVE_LIBC
+ dev->fd = -1;
+#endif
+ dev->evtchn = start_info.console.domU.evtchn;
+ dev->ring = (struct xencons_interface *) mfn_to_virt(start_info.console.domU.mfn);
+
+ err = bind_evtchn(dev->evtchn, console_handle_input, dev);
+ if (err <= 0) {
+ printk("XEN console request chn bind failed %i\n", err);
+ free(dev);
+ return NULL;
+ }
+ unmask_evtchn(dev->evtchn);
+
+ /* In case we have in-flight data after save/restore... */
+ notify_daemon(dev);
+
+ return dev;
+}
+
+void xencons_resume(void)
+{
+ (void)xencons_ring_init();
+}
+
--- /dev/null
+/*
+ * daytime.c: a simple network service based on lwIP and mini-os
+ *
+ * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
+ */
+
+#include <os.h>
+#include <xmalloc.h>
+#include <console.h>
+#include <netfront.h>
+#include <lwip/api.h>
+
+static char message[29];
+
+void run_server(void *p)
+{
+ struct ip_addr listenaddr = { 0 };
+ struct netconn *listener;
+ struct netconn *session;
+ struct timeval tv;
+ err_t rc;
+
+ start_networking();
+
+ if (0) {
+ struct ip_addr ipaddr = { htonl(0x0a000001) };
+ struct ip_addr netmask = { htonl(0xff000000) };
+ struct ip_addr gw = { 0 };
+ networking_set_addr(&ipaddr, &netmask, &gw);
+ }
+
+ tprintk("Opening connection\n");
+
+ listener = netconn_new(NETCONN_TCP);
+ tprintk("Connection at %p\n", listener);
+
+ rc = netconn_bind(listener, &listenaddr, 13);
+ if (rc != ERR_OK) {
+ tprintk("Failed to bind connection: %i\n", rc);
+ return;
+ }
+
+ rc = netconn_listen(listener);
+ if (rc != ERR_OK) {
+ tprintk("Failed to listen on connection: %i\n", rc);
+ return;
+ }
+
+ while (1) {
+ session = netconn_accept(listener);
+ if (session == NULL)
+ continue;
+
+ gettimeofday(&tv, NULL);
+ sprintf(message, "%20lu.%6.6lu\n", tv.tv_sec, tv.tv_usec);
+ (void) netconn_write(session, message, strlen(message), NETCONN_COPY);
+ (void) netconn_disconnect(session);
+ (void) netconn_delete(session);
+ }
+}
+
+
+int app_main(start_info_t *si)
+{
+ create_thread("server", run_server, NULL);
+ return 0;
+}
--- /dev/null
+# -*- mode: python; -*-
+#============================================================================
+# Python configuration setup for 'xm create'.
+# This script sets the parameters used when a domain is created using 'xm create'.
+# You use a separate script for each domain you want to create, or
+# you can set the parameters for the domain on the xm command line.
+#============================================================================
+
+#----------------------------------------------------------------------------
+# Kernel image file.
+kernel = "mini-os.gz"
+
+# Initial memory allocation (in megabytes) for the new domain.
+memory = 32
+
+# A name for your domain. All domains must have different names.
+name = "Mini-OS"
+
+on_crash = 'destroy'
--- /dev/null
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: events.c
+ * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
+ * Changes: Grzegorz Milos (gm281@cam.ac.uk)
+ *
+ * Date: Jul 2003, changes Jun 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: Deals with events recieved on event channels
+ *
+ ****************************************************************************
+ */
+
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/events.h>
+#include <mini-os/lib.h>
+#include <xen/xsm/flask_op.h>
+
+#define NR_EVS 1024
+
+/* this represents a event handler. Chaining or sharing is not allowed */
+typedef struct _ev_action_t {
+ evtchn_handler_t handler;
+ void *data;
+ uint32_t count;
+} ev_action_t;
+
+static ev_action_t ev_actions[NR_EVS];
+void default_handler(evtchn_port_t port, struct pt_regs *regs, void *data);
+
+static unsigned long bound_ports[NR_EVS/(8*sizeof(unsigned long))];
+
+void unbind_all_ports(void)
+{
+ int i;
+ int cpu = 0;
+ shared_info_t *s = HYPERVISOR_shared_info;
+ vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
+
+ for ( i = 0; i < NR_EVS; i++ )
+ {
+ if ( i == start_info.console.domU.evtchn ||
+ i == start_info.store_evtchn)
+ continue;
+
+ if ( test_and_clear_bit(i, bound_ports) )
+ {
+ printk("port %d still bound!\n", i);
+ unbind_evtchn(i);
+ }
+ }
+ vcpu_info->evtchn_upcall_pending = 0;
+ vcpu_info->evtchn_pending_sel = 0;
+}
+
+/*
+ * Demux events to different handlers.
+ */
+int do_event(evtchn_port_t port, struct pt_regs *regs)
+{
+ ev_action_t *action;
+
+ clear_evtchn(port);
+
+ if ( port >= NR_EVS )
+ {
+ printk("WARN: do_event(): Port number too large: %d\n", port);
+ return 1;
+ }
+
+ action = &ev_actions[port];
+ action->count++;
+
+ /* call the handler */
+ action->handler(port, regs, action->data);
+
+ return 1;
+
+}
+
+evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler,
+ void *data)
+{
+ if ( ev_actions[port].handler != default_handler )
+ printk("WARN: Handler for port %d already registered, replacing\n",
+ port);
+
+ ev_actions[port].data = data;
+ wmb();
+ ev_actions[port].handler = handler;
+ set_bit(port, bound_ports);
+
+ return port;
+}
+
+void unbind_evtchn(evtchn_port_t port )
+{
+ struct evtchn_close close;
+ int rc;
+
+ if ( ev_actions[port].handler == default_handler )
+ printk("WARN: No handler for port %d when unbinding\n", port);
+ mask_evtchn(port);
+ clear_evtchn(port);
+
+ ev_actions[port].handler = default_handler;
+ wmb();
+ ev_actions[port].data = NULL;
+ clear_bit(port, bound_ports);
+
+ close.port = port;
+ rc = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
+ if ( rc )
+ printk("WARN: close_port %d failed rc=%d. ignored\n", port, rc);
+}
+
+evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
+{
+ evtchn_bind_virq_t op;
+ int rc;
+
+ /* Try to bind the virq to a port */
+ op.virq = virq;
+ op.vcpu = smp_processor_id();
+
+ rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op);
+ if (rc != 0)
+ {
+ printk("Failed to bind virtual IRQ %d with rc=%d\n", virq, rc);
+ return -1;
+ }
+ bind_evtchn(op.port, handler, data);
+ return op.port;
+}
+
+evtchn_port_t bind_pirq(uint32_t pirq, int will_share,
+ evtchn_handler_t handler, void *data)
+{
+ evtchn_bind_pirq_t op;
+ int rc;
+
+ /* Try to bind the pirq to a port */
+ op.pirq = pirq;
+ op.flags = will_share ? BIND_PIRQ__WILL_SHARE : 0;
+
+ if ( (rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &op)) != 0 )
+ {
+ printk("Failed to bind physical IRQ %d with rc=%d\n", pirq, rc);
+ return -1;
+ }
+ bind_evtchn(op.port, handler, data);
+ return op.port;
+}
+
+/*
+ * Initially all events are without a handler and disabled
+ */
+void init_events(void)
+{
+ int i;
+
+ /* initialize event handler */
+ for ( i = 0; i < NR_EVS; i++ )
+ {
+ ev_actions[i].handler = default_handler;
+ mask_evtchn(i);
+ }
+
+ arch_init_events();
+}
+
+void fini_events(void)
+{
+ /* Dealloc all events */
+ arch_unbind_ports();
+ unbind_all_ports();
+ arch_fini_events();
+}
+
+void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore)
+{
+ printk("[Port %d] - event received\n", port);
+}
+
+/* Create a port available to the pal for exchanging notifications.
+ Returns the result of the hypervisor call. */
+
+/* Unfortunate confusion of terminology: the port is unbound as far
+ as Xen is concerned, but we automatically bind a handler to it
+ from inside mini-os. */
+
+int evtchn_alloc_unbound(domid_t pal, evtchn_handler_t handler,
+ void *data, evtchn_port_t *port)
+{
+ int rc;
+
+ evtchn_alloc_unbound_t op;
+ op.dom = DOMID_SELF;
+ op.remote_dom = pal;
+ rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
+ if ( rc )
+ {
+ printk("ERROR: alloc_unbound failed with rc=%d", rc);
+ return rc;
+ }
+ *port = bind_evtchn(op.port, handler, data);
+ return rc;
+}
+
+/* Connect to a port so as to allow the exchange of notifications with
+ the pal. Returns the result of the hypervisor call. */
+
+int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port,
+ evtchn_handler_t handler, void *data,
+ evtchn_port_t *local_port)
+{
+ int rc;
+ evtchn_port_t port;
+ evtchn_bind_interdomain_t op;
+ op.remote_dom = pal;
+ op.remote_port = remote_port;
+ rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, &op);
+ if ( rc )
+ {
+ printk("ERROR: bind_interdomain failed with rc=%d", rc);
+ return rc;
+ }
+ port = op.local_port;
+ *local_port = bind_evtchn(port, handler, data);
+ return rc;
+}
+
+int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size)
+{
+ int rc;
+ uint32_t sid;
+ struct xen_flask_op op;
+ op.cmd = FLASK_GET_PEER_SID;
+ op.interface_version = XEN_FLASK_INTERFACE_VERSION;
+ op.u.peersid.evtchn = local_port;
+ rc = HYPERVISOR_xsm_op(&op);
+ if (rc)
+ return rc;
+ sid = op.u.peersid.sid;
+ op.cmd = FLASK_SID_TO_CONTEXT;
+ op.u.sid_context.sid = sid;
+ op.u.sid_context.size = size;
+ set_xen_guest_handle(op.u.sid_context.context, ctx);
+ rc = HYPERVISOR_xsm_op(&op);
+ return rc;
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/*
+ * Frame Buffer + Keyboard driver for Mini-OS.
+ * Samuel Thibault <samuel.thibault@eu.citrix.com>, 2008
+ * Based on blkfront.c.
+ */
+
+#include <mini-os/os.h>
+#include <mini-os/xenbus.h>
+#include <mini-os/events.h>
+#include <xen/io/kbdif.h>
+#include <xen/io/fbif.h>
+#include <xen/io/protocols.h>
+#include <mini-os/gnttab.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/fbfront.h>
+#include <mini-os/lib.h>
+
+DECLARE_WAIT_QUEUE_HEAD(kbdfront_queue);
+
+
+
+
+
+
+struct kbdfront_dev {
+ domid_t dom;
+
+ struct xenkbd_page *page;
+ evtchn_port_t evtchn;
+
+ char *nodename;
+ char *backend;
+
+ xenbus_event_queue events;
+
+#ifdef HAVE_LIBC
+ int fd;
+#endif
+};
+
+void kbdfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+#ifdef HAVE_LIBC
+ struct kbdfront_dev *dev = data;
+ int fd = dev->fd;
+
+ if (fd != -1)
+ files[fd].read = 1;
+#endif
+ wake_up(&kbdfront_queue);
+}
+
+static void free_kbdfront(struct kbdfront_dev *dev)
+{
+ mask_evtchn(dev->evtchn);
+
+ free(dev->backend);
+
+ free_page(dev->page);
+
+ unbind_evtchn(dev->evtchn);
+
+ free(dev->nodename);
+ free(dev);
+}
+
+struct kbdfront_dev *init_kbdfront(char *_nodename, int abs_pointer)
+{
+ xenbus_transaction_t xbt;
+ char* err;
+ char* message=NULL;
+ struct xenkbd_page *s;
+ int retry=0;
+ char* msg = NULL;
+ char* nodename = _nodename ? _nodename : "device/vkbd/0";
+ struct kbdfront_dev *dev;
+
+ char path[strlen(nodename) + strlen("/backend-id") + 1];
+
+ printk("******************* KBDFRONT for %s **********\n\n\n", nodename);
+
+ dev = malloc(sizeof(*dev));
+ memset(dev, 0, sizeof(*dev));
+ dev->nodename = strdup(nodename);
+#ifdef HAVE_LIBC
+ dev->fd = -1;
+#endif
+
+ snprintf(path, sizeof(path), "%s/backend-id", nodename);
+ dev->dom = xenbus_read_integer(path);
+ evtchn_alloc_unbound(dev->dom, kbdfront_handler, dev, &dev->evtchn);
+
+ dev->page = s = (struct xenkbd_page*) alloc_page();
+ memset(s,0,PAGE_SIZE);
+
+ dev->events = NULL;
+
+ s->in_cons = s->in_prod = 0;
+ s->out_cons = s->out_prod = 0;
+
+again:
+ err = xenbus_transaction_start(&xbt);
+ if (err) {
+ printk("starting transaction\n");
+ free(err);
+ }
+
+ err = xenbus_printf(xbt, nodename, "page-ref","%lu", virt_to_mfn(s));
+ if (err) {
+ message = "writing page-ref";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn);
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+ if (abs_pointer) {
+ err = xenbus_printf(xbt, nodename, "request-abs-pointer", "1");
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+ }
+
+ snprintf(path, sizeof(path), "%s/state", nodename);
+ err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
+ if (err) {
+ printk("error writing initialized: %s\n", err);
+ free(err);
+ }
+
+ err = xenbus_transaction_end(xbt, 0, &retry);
+ free(err);
+ if (retry) {
+ goto again;
+ printk("completing transaction\n");
+ }
+
+ goto done;
+
+abort_transaction:
+ free(err);
+ err = xenbus_transaction_end(xbt, 1, &retry);
+ printk("Abort transaction %s\n", message);
+ goto error;
+
+done:
+
+ snprintf(path, sizeof(path), "%s/backend", nodename);
+ msg = xenbus_read(XBT_NIL, path, &dev->backend);
+ if (msg) {
+ printk("Error %s when reading the backend path %s\n", msg, path);
+ goto error;
+ }
+
+ printk("backend at %s\n", dev->backend);
+
+ {
+ XenbusState state;
+ char path[strlen(dev->backend) + strlen("/state") + 1];
+ char frontpath[strlen(nodename) + strlen("/state") + 1];
+
+ snprintf(path, sizeof(path), "%s/state", dev->backend);
+
+ xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
+
+ err = NULL;
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateConnected)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ if (state != XenbusStateConnected) {
+ printk("backend not available, state=%d\n", state);
+ free(err);
+ err = xenbus_unwatch_path_token(XBT_NIL, path, path);
+ goto error;
+ }
+
+ printk("%s connected\n", dev->backend);
+
+ snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
+ if((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
+ != NULL) {
+ printk("error switching state: %s\n", err);
+ free(err);
+ err = xenbus_unwatch_path_token(XBT_NIL, path, path);
+ goto error;
+ }
+ }
+ unmask_evtchn(dev->evtchn);
+
+ printk("************************** KBDFRONT\n");
+
+ return dev;
+error:
+ free(msg);
+ free(err);
+ free_kbdfront(dev);
+ return NULL;
+}
+
+int kbdfront_receive(struct kbdfront_dev *dev, union xenkbd_in_event *buf, int n)
+{
+ struct xenkbd_page *page = dev->page;
+ uint32_t prod, cons;
+ int i;
+
+#ifdef HAVE_LIBC
+ if (dev->fd != -1) {
+ files[dev->fd].read = 0;
+ mb(); /* Make sure to let the handler set read to 1 before we start looking at the ring */
+ }
+#endif
+
+ prod = page->in_prod;
+
+ if (prod == page->in_cons)
+ return 0;
+
+ rmb(); /* ensure we see ring contents up to prod */
+
+ for (i = 0, cons = page->in_cons; i < n && cons != prod; i++, cons++)
+ memcpy(buf + i, &XENKBD_IN_RING_REF(page, cons), sizeof(*buf));
+
+ mb(); /* ensure we got ring contents */
+ page->in_cons = cons;
+ notify_remote_via_evtchn(dev->evtchn);
+
+#ifdef HAVE_LIBC
+ if (cons != prod && dev->fd != -1)
+ /* still some events to read */
+ files[dev->fd].read = 1;
+#endif
+
+ return i;
+}
+
+
+void shutdown_kbdfront(struct kbdfront_dev *dev)
+{
+ char* err = NULL, *err2;
+ XenbusState state;
+
+ char path[strlen(dev->backend) + strlen("/state") + 1];
+ char nodename[strlen(dev->nodename) + strlen("/request-abs-pointer") + 1];
+
+ printk("close kbd: backend at %s\n",dev->backend);
+
+ snprintf(path, sizeof(path), "%s/state", dev->backend);
+ snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
+ printk("shutdown_kbdfront: error changing state to %d: %s\n",
+ XenbusStateClosing, err);
+ goto close_kbdfront;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateClosing)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ free(err);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
+ printk("shutdown_kbdfront: error changing state to %d: %s\n",
+ XenbusStateClosed, err);
+ goto close_kbdfront;
+ }
+ state = xenbus_read_integer(path);
+ while (state < XenbusStateClosed) {
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ free(err);
+ }
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
+ printk("shutdown_kbdfront: error changing state to %d: %s\n",
+ XenbusStateInitialising, err);
+ goto close_kbdfront;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+
+close_kbdfront:
+ free(err);
+ err2 = xenbus_unwatch_path_token(XBT_NIL, path, path);
+ free(err2);
+
+ snprintf(nodename, sizeof(nodename), "%s/page-ref", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+ snprintf(nodename, sizeof(nodename), "%s/event-channel", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+ snprintf(nodename, sizeof(nodename), "%s/request-abs-pointer", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+
+ if (!err)
+ free_kbdfront(dev);
+}
+
+#ifdef HAVE_LIBC
+int kbdfront_open(struct kbdfront_dev *dev)
+{
+ dev->fd = alloc_fd(FTYPE_KBD);
+ printk("kbd_open(%s) -> %d\n", dev->nodename, dev->fd);
+ files[dev->fd].kbd.dev = dev;
+ return dev->fd;
+}
+#endif
+
+
+
+
+
+DECLARE_WAIT_QUEUE_HEAD(fbfront_queue);
+
+
+
+
+
+
+struct fbfront_dev {
+ domid_t dom;
+
+ struct xenfb_page *page;
+ evtchn_port_t evtchn;
+
+ char *nodename;
+ char *backend;
+ int request_update;
+
+ int width;
+ int height;
+ int depth;
+ int stride;
+ int mem_length;
+ int offset;
+
+ xenbus_event_queue events;
+
+#ifdef HAVE_LIBC
+ int fd;
+#endif
+};
+
+void fbfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+#ifdef HAVE_LIBC
+ struct fbfront_dev *dev = data;
+ int fd = dev->fd;
+
+ if (fd != -1)
+ files[fd].read = 1;
+#endif
+ wake_up(&fbfront_queue);
+}
+
+static void free_fbfront(struct fbfront_dev *dev)
+{
+ mask_evtchn(dev->evtchn);
+
+ free(dev->backend);
+
+ free_page(dev->page);
+
+ unbind_evtchn(dev->evtchn);
+
+ free(dev->nodename);
+ free(dev);
+}
+
+int fbfront_receive(struct fbfront_dev *dev, union xenfb_in_event *buf, int n)
+{
+ struct xenfb_page *page = dev->page;
+ uint32_t prod, cons;
+ int i;
+
+#ifdef HAVE_LIBC
+ if (dev->fd != -1) {
+ files[dev->fd].read = 0;
+ mb(); /* Make sure to let the handler set read to 1 before we start looking at the ring */
+ }
+#endif
+
+ prod = page->in_prod;
+
+ if (prod == page->in_cons)
+ return 0;
+
+ rmb(); /* ensure we see ring contents up to prod */
+
+ for (i = 0, cons = page->in_cons; i < n && cons != prod; i++, cons++)
+ memcpy(buf + i, &XENFB_IN_RING_REF(page, cons), sizeof(*buf));
+
+ mb(); /* ensure we got ring contents */
+ page->in_cons = cons;
+ notify_remote_via_evtchn(dev->evtchn);
+
+#ifdef HAVE_LIBC
+ if (cons != prod && dev->fd != -1)
+ /* still some events to read */
+ files[dev->fd].read = 1;
+#endif
+
+ return i;
+}
+
+struct fbfront_dev *init_fbfront(char *_nodename, unsigned long *mfns, int width, int height, int depth, int stride, int n)
+{
+ xenbus_transaction_t xbt;
+ char* err;
+ char* message=NULL;
+ struct xenfb_page *s;
+ int retry=0;
+ char* msg=NULL;
+ int i, j;
+ struct fbfront_dev *dev;
+ int max_pd;
+ unsigned long mapped;
+ char* nodename = _nodename ? _nodename : "device/vfb/0";
+
+ char path[strlen(nodename) + strlen("/backend-id") + 1];
+
+ printk("******************* FBFRONT for %s **********\n\n\n", nodename);
+
+ dev = malloc(sizeof(*dev));
+ memset(dev, 0, sizeof(*dev));
+ dev->nodename = strdup(nodename);
+#ifdef HAVE_LIBC
+ dev->fd = -1;
+#endif
+
+ snprintf(path, sizeof(path), "%s/backend-id", nodename);
+ dev->dom = xenbus_read_integer(path);
+ evtchn_alloc_unbound(dev->dom, fbfront_handler, dev, &dev->evtchn);
+
+ dev->page = s = (struct xenfb_page*) alloc_page();
+ memset(s,0,PAGE_SIZE);
+
+ s->in_cons = s->in_prod = 0;
+ s->out_cons = s->out_prod = 0;
+ dev->width = s->width = width;
+ dev->height = s->height = height;
+ dev->depth = s->depth = depth;
+ dev->stride = s->line_length = stride;
+ dev->mem_length = s->mem_length = n * PAGE_SIZE;
+ dev->offset = 0;
+ dev->events = NULL;
+
+ max_pd = sizeof(s->pd) / sizeof(s->pd[0]);
+ mapped = 0;
+
+ for (i = 0; mapped < n && i < max_pd; i++) {
+ unsigned long *pd = (unsigned long *) alloc_page();
+ for (j = 0; mapped < n && j < PAGE_SIZE / sizeof(unsigned long); j++)
+ pd[j] = mfns[mapped++];
+ for ( ; j < PAGE_SIZE / sizeof(unsigned long); j++)
+ pd[j] = 0;
+ s->pd[i] = virt_to_mfn(pd);
+ }
+ for ( ; i < max_pd; i++)
+ s->pd[i] = 0;
+
+
+again:
+ err = xenbus_transaction_start(&xbt);
+ if (err) {
+ printk("starting transaction\n");
+ free(err);
+ }
+
+ err = xenbus_printf(xbt, nodename, "page-ref","%lu", virt_to_mfn(s));
+ if (err) {
+ message = "writing page-ref";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn);
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(xbt, nodename, "protocol", "%s",
+ XEN_IO_PROTO_ABI_NATIVE);
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(xbt, nodename, "feature-update", "1");
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+
+ snprintf(path, sizeof(path), "%s/state", nodename);
+ err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
+ if (err) {
+ message = "switching state";
+ goto abort_transaction;
+ }
+
+ err = xenbus_transaction_end(xbt, 0, &retry);
+ free(err);
+ if (retry) {
+ goto again;
+ printk("completing transaction\n");
+ }
+
+ goto done;
+
+abort_transaction:
+ free(err);
+ err = xenbus_transaction_end(xbt, 1, &retry);
+ printk("Abort transaction %s\n", message);
+ goto error;
+
+done:
+
+ snprintf(path, sizeof(path), "%s/backend", nodename);
+ msg = xenbus_read(XBT_NIL, path, &dev->backend);
+ if (msg) {
+ printk("Error %s when reading the backend path %s\n", msg, path);
+ goto error;
+ }
+
+ printk("backend at %s\n", dev->backend);
+
+ {
+ XenbusState state;
+ char path[strlen(dev->backend) + strlen("/request-update") + 1];
+ char frontpath[strlen(nodename) + strlen("/state") + 1];
+
+ snprintf(path, sizeof(path), "%s/state", dev->backend);
+
+ xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
+
+ err = NULL;
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateConnected)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ if (state != XenbusStateConnected) {
+ printk("backend not available, state=%d\n", state);
+ free(err);
+ err = xenbus_unwatch_path_token(XBT_NIL, path, path);
+ goto error;
+ }
+
+ printk("%s connected\n", dev->backend);
+
+ snprintf(path, sizeof(path), "%s/request-update", dev->backend);
+ dev->request_update = xenbus_read_integer(path);
+
+ snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
+ if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
+ != NULL) {
+ printk("error switching state: %s\n", err);
+ free(err);
+ err = xenbus_unwatch_path_token(XBT_NIL, path, path);
+ goto error;
+ }
+ }
+ unmask_evtchn(dev->evtchn);
+
+ printk("************************** FBFRONT\n");
+
+ return dev;
+
+error:
+ free(msg);
+ free(err);
+ free_fbfront(dev);
+ return NULL;
+}
+
+static void fbfront_out_event(struct fbfront_dev *dev, union xenfb_out_event *event)
+{
+ struct xenfb_page *page = dev->page;
+ uint32_t prod;
+ DEFINE_WAIT(w);
+
+ add_waiter(w, fbfront_queue);
+ while (page->out_prod - page->out_cons == XENFB_OUT_RING_LEN)
+ schedule();
+ remove_waiter(w, fbfront_queue);
+
+ prod = page->out_prod;
+ mb(); /* ensure ring space available */
+ XENFB_OUT_RING_REF(page, prod) = *event;
+ wmb(); /* ensure ring contents visible */
+ page->out_prod = prod + 1;
+ notify_remote_via_evtchn(dev->evtchn);
+}
+
+void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int height)
+{
+ struct xenfb_update update;
+
+ if (dev->request_update <= 0)
+ return;
+
+ if (x < 0) {
+ width += x;
+ x = 0;
+ }
+ if (x + width > dev->width)
+ width = dev->width - x;
+
+ if (y < 0) {
+ height += y;
+ y = 0;
+ }
+ if (y + height > dev->height)
+ height = dev->height - y;
+
+ if (width <= 0 || height <= 0)
+ return;
+
+ update.type = XENFB_TYPE_UPDATE;
+ update.x = x;
+ update.y = y;
+ update.width = width;
+ update.height = height;
+ fbfront_out_event(dev, (union xenfb_out_event *) &update);
+}
+
+void fbfront_resize(struct fbfront_dev *dev, int width, int height, int stride, int depth, int offset)
+{
+ struct xenfb_resize resize;
+
+ resize.type = XENFB_TYPE_RESIZE;
+ dev->width = resize.width = width;
+ dev->height = resize.height = height;
+ dev->stride = resize.stride = stride;
+ dev->depth = resize.depth = depth;
+ dev->offset = resize.offset = offset;
+ fbfront_out_event(dev, (union xenfb_out_event *) &resize);
+}
+
+void shutdown_fbfront(struct fbfront_dev *dev)
+{
+ char* err = NULL, *err2;
+ XenbusState state;
+
+ char path[strlen(dev->backend) + strlen("/state") + 1];
+ char nodename[strlen(dev->nodename) + strlen("/feature-update") + 1];
+
+ printk("close fb: backend at %s\n",dev->backend);
+
+ snprintf(path, sizeof(path), "%s/state", dev->backend);
+ snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
+ printk("shutdown_fbfront: error changing state to %d: %s\n",
+ XenbusStateClosing, err);
+ goto close_fbfront;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateClosing)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ free(err);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
+ printk("shutdown_fbfront: error changing state to %d: %s\n",
+ XenbusStateClosed, err);
+ goto close_fbfront;
+ }
+ state = xenbus_read_integer(path);
+ if (state < XenbusStateClosed) {
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ free(err);
+ }
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
+ printk("shutdown_fbfront: error changing state to %d: %s\n",
+ XenbusStateInitialising, err);
+ goto close_fbfront;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+
+close_fbfront:
+ free(err);
+ err2 = xenbus_unwatch_path_token(XBT_NIL, path, path);
+ free(err2);
+
+ snprintf(nodename, sizeof(nodename), "%s/page-ref", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+ snprintf(nodename, sizeof(nodename), "%s/event-channel", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+ snprintf(nodename, sizeof(nodename), "%s/protocol", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+ snprintf(nodename, sizeof(nodename), "%s/feature-update", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+
+ if (!err)
+ free_fbfront(dev);
+}
+
+#ifdef HAVE_LIBC
+int fbfront_open(struct fbfront_dev *dev)
+{
+ dev->fd = alloc_fd(FTYPE_FB);
+ printk("fb_open(%s) -> %d\n", dev->nodename, dev->fd);
+ files[dev->fd].fb.dev = dev;
+ return dev->fd;
+}
+#endif
+
--- /dev/null
+/*
+ * Manages grant mappings from other domains.
+ *
+ * Diego Ongaro <diego.ongaro@citrix.com>, July 2008
+ *
+ * Files of type FTYPE_GNTMAP contain a gntmap, which is an array of
+ * (host address, grant handle) pairs. Grant handles come from a hypervisor map
+ * operation and are needed for the corresponding unmap.
+ *
+ * This is a rather naive implementation in terms of performance. If we start
+ * using it frequently, there's definitely some low-hanging fruit here.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <mini-os/os.h>
+#include <mini-os/lib.h>
+#include <mini-os/xmalloc.h>
+#include <errno.h>
+#include <xen/grant_table.h>
+#include <inttypes.h>
+#include <mini-os/gntmap.h>
+
+//#define GNTMAP_DEBUG
+#ifdef GNTMAP_DEBUG
+#define DEBUG(_f, _a...) \
+ printk("MINI_OS(gntmap.c:%d): %s" _f "\n", __LINE__, __func__, ## _a)
+#else
+#define DEBUG(_f, _a...) ((void)0)
+#endif
+
+
+#define DEFAULT_MAX_GRANTS 128
+
+struct gntmap_entry {
+ unsigned long host_addr;
+ grant_handle_t handle;
+};
+
+static inline int
+gntmap_entry_used(struct gntmap_entry *entry)
+{
+ return entry->host_addr != 0;
+}
+
+static struct gntmap_entry*
+gntmap_find_free_entry(struct gntmap *map)
+{
+ int i;
+
+ for (i = 0; i < map->nentries; i++) {
+ if (!gntmap_entry_used(&map->entries[i]))
+ return &map->entries[i];
+ }
+
+ DEBUG("(map=%p): all %d entries full",
+ map, map->nentries);
+ return NULL;
+}
+
+static struct gntmap_entry*
+gntmap_find_entry(struct gntmap *map, unsigned long addr)
+{
+ int i;
+
+ for (i = 0; i < map->nentries; i++) {
+ if (map->entries[i].host_addr == addr)
+ return &map->entries[i];
+ }
+ return NULL;
+}
+
+int
+gntmap_set_max_grants(struct gntmap *map, int count)
+{
+ DEBUG("(map=%p, count=%d)", map, count);
+
+ if (map->nentries != 0)
+ return -EBUSY;
+
+ map->entries = xmalloc_array(struct gntmap_entry, count);
+ if (map->entries == NULL)
+ return -ENOMEM;
+
+ memset(map->entries, 0, sizeof(struct gntmap_entry) * count);
+ map->nentries = count;
+ return 0;
+}
+
+static int
+_gntmap_map_grant_ref(struct gntmap_entry *entry,
+ unsigned long host_addr,
+ uint32_t domid,
+ uint32_t ref,
+ int writable)
+{
+ struct gnttab_map_grant_ref op;
+ int rc;
+
+ op.ref = (grant_ref_t) ref;
+ op.dom = (domid_t) domid;
+ op.host_addr = (uint64_t) host_addr;
+ op.flags = GNTMAP_host_map;
+ if (!writable)
+ op.flags |= GNTMAP_readonly;
+
+ rc = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
+ if (rc != 0 || op.status != GNTST_okay) {
+ printk("GNTTABOP_map_grant_ref failed: "
+ "returned %d, status %" PRId16 "\n",
+ rc, op.status);
+ return rc != 0 ? rc : op.status;
+ }
+
+ entry->host_addr = host_addr;
+ entry->handle = op.handle;
+ return 0;
+}
+
+static int
+_gntmap_unmap_grant_ref(struct gntmap_entry *entry)
+{
+ struct gnttab_unmap_grant_ref op;
+ int rc;
+
+ op.host_addr = (uint64_t) entry->host_addr;
+ op.dev_bus_addr = 0;
+ op.handle = entry->handle;
+
+ rc = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
+ if (rc != 0 || op.status != GNTST_okay) {
+ printk("GNTTABOP_unmap_grant_ref failed: "
+ "returned %d, status %" PRId16 "\n",
+ rc, op.status);
+ return rc != 0 ? rc : op.status;
+ }
+
+ entry->host_addr = 0;
+ return 0;
+}
+
+int
+gntmap_munmap(struct gntmap *map, unsigned long start_address, int count)
+{
+ int i, rc;
+ struct gntmap_entry *ent;
+
+ DEBUG("(map=%p, start_address=%lx, count=%d)",
+ map, start_address, count);
+
+ for (i = 0; i < count; i++) {
+ ent = gntmap_find_entry(map, start_address + PAGE_SIZE * i);
+ if (ent == NULL) {
+ printk("gntmap: tried to munmap unknown page\n");
+ return -EINVAL;
+ }
+
+ rc = _gntmap_unmap_grant_ref(ent);
+ if (rc != 0)
+ return rc;
+ }
+
+ return 0;
+}
+
+void*
+gntmap_map_grant_refs(struct gntmap *map,
+ uint32_t count,
+ uint32_t *domids,
+ int domids_stride,
+ uint32_t *refs,
+ int writable)
+{
+ unsigned long addr;
+ struct gntmap_entry *ent;
+ int i;
+
+ DEBUG("(map=%p, count=%" PRIu32 ", "
+ "domids=%p [%" PRIu32 "...], domids_stride=%d, "
+ "refs=%p [%" PRIu32 "...], writable=%d)",
+ map, count,
+ domids, domids == NULL ? 0 : domids[0], domids_stride,
+ refs, refs == NULL ? 0 : refs[0], writable);
+
+ (void) gntmap_set_max_grants(map, DEFAULT_MAX_GRANTS);
+
+ addr = allocate_ondemand((unsigned long) count, 1);
+ if (addr == 0)
+ return NULL;
+
+ for (i = 0; i < count; i++) {
+ ent = gntmap_find_free_entry(map);
+ if (ent == NULL ||
+ _gntmap_map_grant_ref(ent,
+ addr + PAGE_SIZE * i,
+ domids[i * domids_stride],
+ refs[i],
+ writable) != 0) {
+
+ (void) gntmap_munmap(map, addr, i);
+ return NULL;
+ }
+ }
+
+ return (void*) addr;
+}
+
+void
+gntmap_init(struct gntmap *map)
+{
+ DEBUG("(map=%p)", map);
+ map->nentries = 0;
+ map->entries = NULL;
+}
+
+void
+gntmap_fini(struct gntmap *map)
+{
+ struct gntmap_entry *ent;
+ int i;
+
+ DEBUG("(map=%p)", map);
+
+ for (i = 0; i < map->nentries; i++) {
+ ent = &map->entries[i];
+ if (gntmap_entry_used(ent))
+ (void) _gntmap_unmap_grant_ref(ent);
+ }
+
+ xfree(map->entries);
+ map->entries = NULL;
+ map->nentries = 0;
+}
--- /dev/null
+/*
+ ****************************************************************************
+ * (C) 2006 - Cambridge University
+ ****************************************************************************
+ *
+ * File: gnttab.c
+ * Author: Steven Smith (sos22@cam.ac.uk)
+ * Changes: Grzegorz Milos (gm281@cam.ac.uk)
+ *
+ * Date: July 2006
+ *
+ * Environment: Xen Minimal OS
+ * Description: Simple grant tables implementation. About as stupid as it's
+ * possible to be and still work.
+ *
+ ****************************************************************************
+ */
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <mini-os/gnttab.h>
+#include <mini-os/semaphore.h>
+
+#define NR_RESERVED_ENTRIES 8
+
+/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
+#define NR_GRANT_FRAMES 4
+#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
+
+static grant_entry_t *gnttab_table;
+static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
+#ifdef GNT_DEBUG
+static char inuse[NR_GRANT_ENTRIES];
+#endif
+static __DECLARE_SEMAPHORE_GENERIC(gnttab_sem, 0);
+
+static void
+put_free_entry(grant_ref_t ref)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+#ifdef GNT_DEBUG
+ BUG_ON(!inuse[ref]);
+ inuse[ref] = 0;
+#endif
+ gnttab_list[ref] = gnttab_list[0];
+ gnttab_list[0] = ref;
+ local_irq_restore(flags);
+ up(&gnttab_sem);
+}
+
+static grant_ref_t
+get_free_entry(void)
+{
+ unsigned int ref;
+ unsigned long flags;
+ down(&gnttab_sem);
+ local_irq_save(flags);
+ ref = gnttab_list[0];
+ BUG_ON(ref < NR_RESERVED_ENTRIES || ref >= NR_GRANT_ENTRIES);
+ gnttab_list[0] = gnttab_list[ref];
+#ifdef GNT_DEBUG
+ BUG_ON(inuse[ref]);
+ inuse[ref] = 1;
+#endif
+ local_irq_restore(flags);
+ return ref;
+}
+
+grant_ref_t
+gnttab_grant_access(domid_t domid, unsigned long frame, int readonly)
+{
+ grant_ref_t ref;
+
+ ref = get_free_entry();
+ gnttab_table[ref].frame = frame;
+ gnttab_table[ref].domid = domid;
+ wmb();
+ readonly *= GTF_readonly;
+ gnttab_table[ref].flags = GTF_permit_access | readonly;
+
+ return ref;
+}
+
+grant_ref_t
+gnttab_grant_transfer(domid_t domid, unsigned long pfn)
+{
+ grant_ref_t ref;
+
+ ref = get_free_entry();
+ gnttab_table[ref].frame = pfn;
+ gnttab_table[ref].domid = domid;
+ wmb();
+ gnttab_table[ref].flags = GTF_accept_transfer;
+
+ return ref;
+}
+
+int
+gnttab_end_access(grant_ref_t ref)
+{
+ uint16_t flags, nflags;
+
+ BUG_ON(ref >= NR_GRANT_ENTRIES || ref < NR_RESERVED_ENTRIES);
+
+ nflags = gnttab_table[ref].flags;
+ do {
+ if ((flags = nflags) & (GTF_reading|GTF_writing)) {
+ printk("WARNING: g.e. still in use! (%x)\n", flags);
+ return 0;
+ }
+ } while ((nflags = synch_cmpxchg(&gnttab_table[ref].flags, flags, 0)) !=
+ flags);
+
+ put_free_entry(ref);
+ return 1;
+}
+
+unsigned long
+gnttab_end_transfer(grant_ref_t ref)
+{
+ unsigned long frame;
+ uint16_t flags;
+
+ BUG_ON(ref >= NR_GRANT_ENTRIES || ref < NR_RESERVED_ENTRIES);
+
+ while (!((flags = gnttab_table[ref].flags) & GTF_transfer_committed)) {
+ if (synch_cmpxchg(&gnttab_table[ref].flags, flags, 0) == flags) {
+ printk("Release unused transfer grant.\n");
+ put_free_entry(ref);
+ return 0;
+ }
+ }
+
+ /* If a transfer is in progress then wait until it is completed. */
+ while (!(flags & GTF_transfer_completed)) {
+ flags = gnttab_table[ref].flags;
+ }
+
+ /* Read the frame number /after/ reading completion status. */
+ rmb();
+ frame = gnttab_table[ref].frame;
+
+ put_free_entry(ref);
+
+ return frame;
+}
+
+grant_ref_t
+gnttab_alloc_and_grant(void **map)
+{
+ unsigned long mfn;
+ grant_ref_t gref;
+
+ *map = (void *)alloc_page();
+ mfn = virt_to_mfn(*map);
+ gref = gnttab_grant_access(0, mfn, 0);
+ return gref;
+}
+
+static const char * const gnttabop_error_msgs[] = GNTTABOP_error_msgs;
+
+const char *
+gnttabop_error(int16_t status)
+{
+ status = -status;
+ if (status < 0 || status >= ARRAY_SIZE(gnttabop_error_msgs))
+ return "bad status";
+ else
+ return gnttabop_error_msgs[status];
+}
+
+void
+init_gnttab(void)
+{
+ int i;
+
+#ifdef GNT_DEBUG
+ memset(inuse, 1, sizeof(inuse));
+#endif
+ for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
+ put_free_entry(i);
+
+ gnttab_table = arch_init_gnttab(NR_GRANT_FRAMES);
+ printk("gnttab_table mapped at %p.\n", gnttab_table);
+}
+
+void
+fini_gnttab(void)
+{
+ struct gnttab_setup_table setup;
+
+ setup.dom = DOMID_SELF;
+ setup.nr_frames = 0;
+
+ HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+}
--- /dev/null
+/******************************************************************************
+ * hypervisor.c
+ *
+ * Communication to/from hypervisor.
+ *
+ * Copyright (c) 2002-2003, K A Fraser
+ * Copyright (c) 2005, Grzegorz Milos, gm281@cam.ac.uk,Intel Research Cambridge
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <mini-os/os.h>
+#include <mini-os/lib.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/events.h>
+
+#define active_evtchns(cpu,sh,idx) \
+ ((sh)->evtchn_pending[idx] & \
+ ~(sh)->evtchn_mask[idx])
+
+int in_callback;
+
+void do_hypervisor_callback(struct pt_regs *regs)
+{
+ unsigned long l1, l2, l1i, l2i;
+ unsigned int port;
+ int cpu = 0;
+ shared_info_t *s = HYPERVISOR_shared_info;
+ vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
+
+ in_callback = 1;
+
+ vcpu_info->evtchn_upcall_pending = 0;
+ /* NB x86. No need for a barrier here -- XCHG is a barrier on x86. */
+#if !defined(__i386__) && !defined(__x86_64__)
+ /* Clear master flag /before/ clearing selector flag. */
+ wmb();
+#endif
+ l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
+ while ( l1 != 0 )
+ {
+ l1i = __ffs(l1);
+ l1 &= ~(1UL << l1i);
+
+ while ( (l2 = active_evtchns(cpu, s, l1i)) != 0 )
+ {
+ l2i = __ffs(l2);
+ l2 &= ~(1UL << l2i);
+
+ port = (l1i * (sizeof(unsigned long) * 8)) + l2i;
+ do_event(port, regs);
+ }
+ }
+
+ in_callback = 0;
+}
+
+void force_evtchn_callback(void)
+{
+#ifdef XEN_HAVE_PV_UPCALL_MASK
+ int save;
+#endif
+ vcpu_info_t *vcpu;
+ vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
+#ifdef XEN_HAVE_PV_UPCALL_MASK
+ save = vcpu->evtchn_upcall_mask;
+#endif
+
+ while (vcpu->evtchn_upcall_pending) {
+#ifdef XEN_HAVE_PV_UPCALL_MASK
+ vcpu->evtchn_upcall_mask = 1;
+#endif
+ barrier();
+ do_hypervisor_callback(NULL);
+ barrier();
+#ifdef XEN_HAVE_PV_UPCALL_MASK
+ vcpu->evtchn_upcall_mask = save;
+ barrier();
+#endif
+ };
+}
+
+inline void mask_evtchn(uint32_t port)
+{
+ shared_info_t *s = HYPERVISOR_shared_info;
+ synch_set_bit(port, &s->evtchn_mask[0]);
+}
+
+inline void unmask_evtchn(uint32_t port)
+{
+ shared_info_t *s = HYPERVISOR_shared_info;
+ vcpu_info_t *vcpu_info = &s->vcpu_info[smp_processor_id()];
+
+ synch_clear_bit(port, &s->evtchn_mask[0]);
+
+ /*
+ * The following is basically the equivalent of 'hw_resend_irq'. Just like
+ * a real IO-APIC we 'lose the interrupt edge' if the channel is masked.
+ */
+ if ( synch_test_bit (port, &s->evtchn_pending[0]) &&
+ !synch_test_and_set_bit(port / (sizeof(unsigned long) * 8),
+ &vcpu_info->evtchn_pending_sel) )
+ {
+ vcpu_info->evtchn_upcall_pending = 1;
+#ifdef XEN_HAVE_PV_UPCALL_MASK
+ if ( !vcpu_info->evtchn_upcall_mask )
+#endif
+ force_evtchn_callback();
+ }
+}
+
+inline void clear_evtchn(uint32_t port)
+{
+ shared_info_t *s = HYPERVISOR_shared_info;
+ synch_clear_bit(port, &s->evtchn_pending[0]);
+}
--- /dev/null
+/*
+ * lwip/arch/cc.h
+ *
+ * Compiler-specific types and macros for lwIP running on mini-os
+ *
+ * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
+ */
+
+#ifndef __LWIP_ARCH_CC_H__
+#define __LWIP_ARCH_CC_H__
+
+/* Typedefs for the types used by lwip - */
+#include <mini-os/os.h>
+#include <mini-os/types.h>
+#include <time.h>
+typedef uint8_t u8_t;
+typedef int8_t s8_t;
+typedef uint16_t u16_t;
+typedef int16_t s16_t;
+typedef uint32_t u32_t;
+typedef int32_t s32_t;
+typedef uint64_t u64_t;
+typedef int64_t s64_t;
+typedef uintptr_t mem_ptr_t;
+
+typedef uint16_t u_short;
+
+/* Compiler hints for packing lwip's structures - */
+#define PACK_STRUCT_FIELD(_x) _x
+#define PACK_STRUCT_STRUCT __attribute__ ((packed))
+#define PACK_STRUCT_BEGIN
+#define PACK_STRUCT_END
+
+/* Platform specific diagnostic output - */
+
+extern void lwip_printk(char *fmt, ...);
+#define LWIP_PLATFORM_DIAG(_x) do { lwip_printk _x ; } while (0)
+
+extern void lwip_die(char *fmt, ...);
+#define LWIP_PLATFORM_ASSERT(_x) do { lwip_die(_x); } while(0)
+
+/* "lightweight" synchronization mechanisms - */
+/* SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable. */
+/* SYS_ARCH_PROTECT(x) - enter protection mode. */
+/* SYS_ARCH_UNPROTECT(x) - leave protection mode. */
+
+/* If the compiler does not provide memset() this file must include a */
+/* definition of it, or include a file which defines it. */
+#include <mini-os/lib.h>
+
+/* This file must either include a system-local <errno.h> which defines */
+/* the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO */
+/* to make lwip/arch.h define the codes which are used throughout. */
+#include <errno.h>
+
+/* Not required by the docs, but needed for network-order calculations */
+#ifdef HAVE_LIBC
+#include <machine/endian.h>
+#ifndef BIG_ENDIAN
+#error endian.h does not define byte order
+#endif
+#else
+#include <endian.h>
+#endif
+
+#include <inttypes.h>
+#define S16_F PRIi16
+#define U16_F PRIu16
+#define X16_F PRIx16
+#define S32_F PRIi32
+#define U32_F PRIu32
+#define X32_F PRIx32
+
+#if 0
+#ifndef DBG_ON
+#define DBG_ON LWIP_DBG_ON
+#endif
+#define LWIP_DEBUG DBG_ON
+//#define IP_DEBUG DBG_ON
+#define TCP_DEBUG DBG_ON
+#define TCP_INPUT_DEBUG DBG_ON
+#define TCP_QLEN_DEBUG DBG_ON
+#define TCPIP_DEBUG DBG_ON
+#define DBG_TYPES_ON DBG_ON
+#endif
+
+#endif /* __LWIP_ARCH_CC_H__ */
--- /dev/null
+/*
+ * lwip/arch/perf.h
+ *
+ * Arch-specific performance measurement for lwIP running on mini-os
+ *
+ * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
+ */
+
+#ifndef __LWIP_ARCH_PERF_H__
+#define __LWIP_ARCH_PERF_H__
+
+#define PERF_START do { } while(0)
+#define PERF_STOP(_x) do { (void)(_x); } while (0)
+
+#endif /* __LWIP_ARCH_PERF_H__ */
--- /dev/null
+/*
+ * lwip/arch/sys_arch.h
+ *
+ * Arch-specific semaphores and mailboxes for lwIP running on mini-os
+ *
+ * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
+ */
+
+#ifndef __LWIP_ARCH_SYS_ARCH_H__
+#define __LWIP_ARCH_SYS_ARCH_H__
+
+#include <mini-os/os.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/semaphore.h>
+
+typedef struct semaphore *sys_sem_t;
+#define SYS_SEM_NULL ((sys_sem_t) NULL)
+
+struct mbox {
+ int count;
+ void **messages;
+ struct semaphore read_sem;
+ struct semaphore write_sem;
+ int writer;
+ int reader;
+};
+
+typedef struct mbox *sys_mbox_t;
+#define SYS_MBOX_NULL ((sys_mbox_t) 0)
+
+typedef struct thread *sys_thread_t;
+
+typedef unsigned long sys_prot_t;
+
+#endif /*__LWIP_ARCH_SYS_ARCH_H__ */
--- /dev/null
+#ifndef ARCH_ENDIAN_H
+#error "Do not include arch_endian by itself, include endian.h"
+#else
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+#endif
--- /dev/null
+#ifndef __ARCH_LIMITS_H__
+#define __ARCH_LIMITS_H__
+
+#include <mm.h>
+
+#define __STACK_SIZE_PAGE_ORDER 2
+#define __STACK_SIZE (4 * PAGE_SIZE)
+
+#endif
--- /dev/null
+#ifndef _ARCH_MM_H_
+#define _ARCH_MM_H_
+
+typedef uint64_t paddr_t;
+
+extern char _text, _etext, _erodata, _edata, _end, __bss_start;
+extern int _boot_stack[];
+extern int _boot_stack_end[];
+extern uint32_t physical_address_offset; /* Add this to a virtual address to get the physical address (wraps at 4GB) */
+
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (1 << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+#define L1_PAGETABLE_SHIFT 12
+
+#define to_phys(x) (((paddr_t)(x)+physical_address_offset) & 0xffffffff)
+#define to_virt(x) ((void *)(((x)-physical_address_offset) & 0xffffffff))
+
+#define PFN_UP(x) (unsigned long)(((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT)
+#define PFN_DOWN(x) (unsigned long)((x) >> L1_PAGETABLE_SHIFT)
+#define PFN_PHYS(x) ((uint64_t)(x) << L1_PAGETABLE_SHIFT)
+#define PHYS_PFN(x) (unsigned long)((x) >> L1_PAGETABLE_SHIFT)
+
+#define virt_to_pfn(_virt) (PFN_DOWN(to_phys(_virt)))
+#define virt_to_mfn(_virt) (PFN_DOWN(to_phys(_virt)))
+#define mfn_to_virt(_mfn) (to_virt(PFN_PHYS(_mfn)))
+#define pfn_to_virt(_pfn) (to_virt(PFN_PHYS(_pfn)))
+
+#define mfn_to_pfn(x) (x)
+#define pfn_to_mfn(x) (x)
+
+#define virtual_to_mfn(_virt) virt_to_mfn(_virt)
+
+// FIXME
+#define map_frames(f, n) (NULL)
+
+#endif
--- /dev/null
+#ifndef __ARCH_SCHED_H__
+#define __ARCH_SCHED_H__
+
+#include "arch_limits.h"
+
+static inline struct thread* get_current(void)
+{
+ struct thread **current;
+ unsigned long sp;
+ __asm__ __volatile__ ("mov %0, sp":"=r"(sp));
+ current = (void *)(unsigned long)(sp & ~(__STACK_SIZE-1));
+ return *current;
+}
+
+void __arch_switch_threads(unsigned long *prevctx, unsigned long *nextctx);
+
+#define arch_switch_threads(prev,next) __arch_switch_threads(&(prev)->sp, &(next)->sp)
+
+#endif /* __ARCH_SCHED_H__ */
--- /dev/null
+#ifndef __ARCH_ASM_SPINLOCK_H
+#define __ARCH_ASM_SPINLOCK_H
+
+#include "os.h"
+
+#define ARCH_SPIN_LOCK_UNLOCKED { 1 }
+
+/*
+ * Simple spin lock operations. There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions. They have a cost.
+ */
+
+#define arch_spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) <= 0)
+#define arch_spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
+
+static inline void _raw_spin_unlock(spinlock_t *lock)
+{
+ xchg(&lock->slock, 1);
+}
+
+static inline int _raw_spin_trylock(spinlock_t *lock)
+{
+ return xchg(&lock->slock, 0) != 0 ? 1 : 0;
+}
+
+static inline void _raw_spin_lock(spinlock_t *lock)
+{
+ volatile int was_locked;
+ do {
+ was_locked = xchg(&lock->slock, 0) == 0 ? 1 : 0;
+ } while(was_locked);
+}
+
+#endif
--- /dev/null
+#define __WORDSIZE 32
--- /dev/null
+void gic_init(void);
--- /dev/null
+/******************************************************************************
+ * hypercall-arm.h
+ *
+ * Copied from XenLinux.
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * 64-bit updates:
+ * Benjamin Liu <benjamin.liu@intel.com>
+ * Jun Nakajima <jun.nakajima@intel.com>
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __HYPERCALL_ARM_H__
+#define __HYPERCALL_ARM_H__
+
+#include <xen/xen.h>
+#include <xen/sched.h>
+#include <xen/xsm/flask_op.h>
+#include <mini-os/mm.h>
+
+int
+HYPERVISOR_sched_op(
+ int cmd, void *arg);
+
+static inline int
+HYPERVISOR_shutdown(
+ unsigned int reason)
+{
+ struct sched_shutdown shutdown = { .reason = reason };
+ HYPERVISOR_sched_op(SCHEDOP_shutdown, &shutdown);
+}
+
+int
+HYPERVISOR_memory_op(
+ unsigned int cmd, void *arg);
+
+int
+HYPERVISOR_event_channel_op(
+ int cmd, void *op);
+
+int
+HYPERVISOR_xen_version(
+ int cmd, void *arg);
+
+int
+HYPERVISOR_console_io(
+ int cmd, int count, char *str);
+
+int
+HYPERVISOR_physdev_op(
+ void *physdev_op);
+
+int
+HYPERVISOR_grant_table_op(
+ unsigned int cmd, void *uop, unsigned int count);
+
+int
+HYPERVISOR_vcpu_op(
+ int cmd, int vcpuid, void *extra_args);
+
+int
+HYPERVISOR_sysctl(
+ unsigned long op);
+
+int
+HYPERVISOR_domctl(
+ unsigned long op);
+
+int
+HYPERVISOR_hvm_op(
+ unsigned long op, void *arg);
+
+int
+HYPERVISOR_xsm_op(
+ struct xen_flask_op *);
+
+#endif /* __HYPERCALL_ARM_H__ */
--- /dev/null
+#ifndef _OS_H_
+#define _OS_H_
+
+#ifndef __ASSEMBLY__
+
+#include <mini-os/hypervisor.h>
+#include <mini-os/types.h>
+#include <mini-os/compiler.h>
+#include <mini-os/kernel.h>
+#include <xen/xen.h>
+
+void arch_fini(void);
+void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign);
+
+extern void *device_tree;
+
+#define BUG() while(1){asm volatile (".word 0xe7f000f0\n");} /* Undefined instruction; will call our fault handler. */
+
+#define smp_processor_id() 0
+
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+extern shared_info_t *HYPERVISOR_shared_info;
+
+// disable interrupts
+static inline void local_irq_disable(void) {
+ __asm__ __volatile__("cpsid i":::"memory");
+}
+
+// enable interrupts
+static inline void local_irq_enable(void) {
+ __asm__ __volatile__("cpsie i":::"memory");
+}
+
+#define local_irq_save(x) { \
+ __asm__ __volatile__("mrs %0, cpsr;cpsid i":"=r"(x)::"memory"); \
+}
+
+#define local_irq_restore(x) { \
+ __asm__ __volatile__("msr cpsr_c, %0"::"r"(x):"memory"); \
+}
+
+#define local_save_flags(x) { \
+ __asm__ __volatile__("mrs %0, cpsr":"=r"(x)::"memory"); \
+}
+
+static inline int irqs_disabled(void) {
+ int x;
+ local_save_flags(x);
+ return x & 0x80;
+}
+
+/* We probably only need "dmb" here, but we'll start by being paranoid. */
+#define mb() __asm__("dsb":::"memory");
+#define rmb() __asm__("dsb":::"memory");
+#define wmb() __asm__("dsb":::"memory");
+
+/************************** arm *******************************/
+#ifdef __INSIDE_MINIOS__
+#if defined (__arm__)
+#define xchg(ptr,v) __atomic_exchange_n(ptr, v, __ATOMIC_SEQ_CST)
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ *
+ * This operation is atomic.
+ * If you need a memory barrier, use synch_test_and_clear_bit instead.
+ */
+static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+{
+ uint8_t *byte = ((uint8_t *)addr) + (nr >> 3);
+ uint8_t bit = 1 << (nr & 7);
+ uint8_t orig;
+
+ orig = __atomic_fetch_and(byte, ~bit, __ATOMIC_RELAXED);
+
+ return (orig & bit) != 0;
+}
+
+/**
+ * Atomically set a bit and return the old value.
+ * Similar to test_and_clear_bit.
+ */
+static __inline__ int test_and_set_bit(int nr, volatile void *base)
+{
+ uint8_t *byte = ((uint8_t *)base) + (nr >> 3);
+ uint8_t bit = 1 << (nr & 7);
+ uint8_t orig;
+
+ orig = __atomic_fetch_or(byte, bit, __ATOMIC_RELAXED);
+
+ return (orig & bit) != 0;
+}
+
+/**
+ * Test whether a bit is set. */
+static __inline__ int test_bit(int nr, const volatile unsigned long *addr)
+{
+ const uint8_t *ptr = (const uint8_t *) addr;
+ return ((1 << (nr & 7)) & (ptr[nr >> 3])) != 0;
+}
+
+/**
+ * Atomically set a bit in memory (like test_and_set_bit but discards result).
+ */
+static __inline__ void set_bit(int nr, volatile unsigned long *addr)
+{
+ test_and_set_bit(nr, addr);
+}
+
+/**
+ * Atomically clear a bit in memory (like test_and_clear_bit but discards result).
+ */
+static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
+{
+ test_and_clear_bit(nr, addr);
+}
+
+/**
+ * __ffs - find first (lowest) set bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static __inline__ unsigned long __ffs(unsigned long word)
+{
+ int clz;
+
+ /* xxxxx10000 = word
+ * xxxxx01111 = word - 1
+ * 0000011111 = word ^ (word - 1)
+ * 4 = 31 - clz(word ^ (word - 1))
+ */
+
+ __asm__ (
+ "sub r0, %[word], #1\n"
+ "eor r0, r0, %[word]\n"
+ "clz %[clz], r0\n":
+ /* Outputs: */
+ [clz] "=r"(clz):
+ /* Inputs: */
+ [word] "r"(word):
+ /* Clobbers: */
+ "r0");
+
+ return 31 - clz;
+}
+
+#else /* ifdef __arm__ */
+#error "Unsupported architecture"
+#endif
+#endif /* ifdef __INSIDE_MINIOS */
+
+/********************* common arm32 and arm64 ****************************/
+
+/* If *ptr == old, then store new there (and return new).
+ * Otherwise, return the old value.
+ * Atomic. */
+#define synch_cmpxchg(ptr, old, new) \
+({ __typeof__(*ptr) stored = old; \
+ __atomic_compare_exchange_n(ptr, &stored, new, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? new : old; \
+})
+
+/* As test_and_clear_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ int synch_test_and_clear_bit(int nr, volatile void *addr)
+{
+ uint8_t *byte = ((uint8_t *)addr) + (nr >> 3);
+ uint8_t bit = 1 << (nr & 7);
+ uint8_t orig;
+
+ orig = __atomic_fetch_and(byte, ~bit, __ATOMIC_SEQ_CST);
+
+ return (orig & bit) != 0;
+}
+
+/* As test_and_set_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ int synch_test_and_set_bit(int nr, volatile void *base)
+{
+ uint8_t *byte = ((uint8_t *)base) + (nr >> 3);
+ uint8_t bit = 1 << (nr & 7);
+ uint8_t orig;
+
+ orig = __atomic_fetch_or(byte, bit, __ATOMIC_SEQ_CST);
+
+ return (orig & bit) != 0;
+}
+
+/* As set_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ void synch_set_bit(int nr, volatile void *addr)
+{
+ synch_test_and_set_bit(nr, addr);
+}
+
+/* As clear_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ void synch_clear_bit(int nr, volatile void *addr)
+{
+ synch_test_and_clear_bit(nr, addr);
+}
+
+/* As test_bit, but with a following memory barrier. */
+static __inline__ int synch_test_bit(int nr, volatile void *addr)
+{
+ int result;
+ result = test_bit(nr, addr);
+ barrier();
+ return result;
+}
+
+#endif /* not assembly */
+
+#endif
--- /dev/null
+#ifndef _TRAPS_H_
+#define _TRAPS_H_
+
+struct pt_regs {
+ unsigned long r0;
+ unsigned long r1;
+ unsigned long r2;
+ unsigned long r3;
+ unsigned long r4;
+ unsigned long r5;
+ unsigned long r6;
+ unsigned long r7;
+ unsigned long r8;
+ unsigned long r9;
+ unsigned long r10;
+ unsigned long r11;
+ unsigned long r12;
+};
+
+#endif
--- /dev/null
+#include <mini-os/wait.h>
+#include <xen/io/blkif.h>
+#include <mini-os/types.h>
+struct blkfront_dev;
+struct blkfront_aiocb
+{
+ struct blkfront_dev *aio_dev;
+ uint8_t *aio_buf;
+ size_t aio_nbytes;
+ off_t aio_offset;
+ size_t total_bytes;
+ uint8_t is_write;
+ void *data;
+
+ grant_ref_t gref[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+ int n;
+
+ void (*aio_cb)(struct blkfront_aiocb *aiocb, int ret);
+};
+struct blkfront_info
+{
+ uint64_t sectors;
+ unsigned sector_size;
+ int mode;
+ int info;
+ int barrier;
+ int flush;
+};
+struct blkfront_dev *init_blkfront(char *nodename, struct blkfront_info *info);
+#ifdef HAVE_LIBC
+#include <sys/stat.h>
+/* POSIX IO functions:
+ * use blkfront_open() to get a file descriptor to the block device
+ * Don't use the other blkfront posix functions here directly, instead use
+ * read(), write(), lseek() and fstat() on the file descriptor
+ */
+int blkfront_open(struct blkfront_dev *dev);
+int blkfront_posix_rwop(int fd, uint8_t* buf, size_t count, int write);
+#define blkfront_posix_write(fd, buf, count) blkfront_posix_rwop(fd, (uint8_t*)buf, count, 1)
+#define blkfront_posix_read(fd, buf, count) blkfront_posix_rwop(fd, (uint8_t*)buf, count, 0)
+int blkfront_posix_fstat(int fd, struct stat* buf);
+#endif
+void blkfront_aio(struct blkfront_aiocb *aiocbp, int write);
+#define blkfront_aio_read(aiocbp) blkfront_aio(aiocbp, 0)
+#define blkfront_aio_write(aiocbp) blkfront_aio(aiocbp, 1)
+void blkfront_io(struct blkfront_aiocb *aiocbp, int write);
+#define blkfront_read(aiocbp) blkfront_io(aiocbp, 0)
+#define blkfront_write(aiocbp) blkfront_io(aiocbp, 1)
+void blkfront_aio_push_operation(struct blkfront_aiocb *aiocbp, uint8_t op);
+int blkfront_aio_poll(struct blkfront_dev *dev);
+void blkfront_sync(struct blkfront_dev *dev);
+void shutdown_blkfront(struct blkfront_dev *dev);
+
+extern struct wait_queue_head blkfront_queue;
--- /dev/null
+#ifndef MINIOS_BYTEORDER_H
+#define MINIOS_BYTEORDER_H
+
+#include <mini-os/byteswap.h>
+#include <mini-os/endian.h>
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define be16_to_cpu(v) bswap_16(v)
+#define be32_to_cpu(v) bswap_32(v)
+#define be64_to_cpu(v) bswap_64(v)
+
+#define le16_to_cpu(v) (v)
+#define le32_to_cpu(v) (v)
+#define le64_to_cpu(v) (v)
+
+#else /*__BIG_ENDIAN*/
+#define be16_to_cpu(v) (v)
+#define be32_to_cpu(v) (v)
+#define be64_to_cpu(v) (v)
+
+#define le16_to_cpu(v) bswap_16(v)
+#define le32_to_cpu(v) bswap_32(v)
+#define le64_to_cpu(v) bswap_64(v)
+
+#endif
+
+#define cpu_to_be16(v) be16_to_cpu(v)
+#define cpu_to_be32(v) be32_to_cpu(v)
+#define cpu_to_be64(v) be64_to_cpu(v)
+
+#define cpu_to_le16(v) le16_to_cpu(v)
+#define cpu_to_le32(v) le32_to_cpu(v)
+#define cpu_to_le64(v) le64_to_cpu(v)
+
+
+#endif
--- /dev/null
+#ifndef _BYTESWAP_H_
+#define _BYTESWAP_H_
+
+/* Unfortunately not provided by newlib. */
+
+#include <mini-os/types.h>
+
+#define bswap_16(x) ((uint16_t)( \
+ (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
+ (((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
+
+/* Use gcc optimized versions if they exist */
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
+#define bswap_32(v) __builtin_bswap32(v)
+#define bswap_64(v) __builtin_bswap64(v)
+#else
+
+#define bswap_32(x) ((uint32_t)( \
+ (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
+ (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
+ (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
+ (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
+
+#define bswap_64(x) ((uint64_t)( \
+ (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
+ (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
+ (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
+ (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
+ (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
+ (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
+ (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
+ (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
+
+#endif
+
+
+
+
+#endif /* _BYTESWAP_H */
--- /dev/null
+#ifndef __MINIOS_COMPILER_H_
+#define __MINIOS_COMPILER_H_
+
+#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
+#define __builtin_expect(x, expected_value) (x)
+#endif
+#define unlikely(x) __builtin_expect(!!(x),0)
+#define likely(x) __builtin_expect(!!(x),1)
+
+#endif /* __MINIOS_COMPILER_H_ */
--- /dev/null
+/*
+ ****************************************************************************
+ * (C) 2006 - Grzegorz Milos - Cambridge University
+ ****************************************************************************
+ *
+ * File: console.h
+ * Author: Grzegorz Milos
+ * Changes:
+ *
+ * Date: Mar 2006
+ *
+ * Environment: Xen Minimal OS
+ * Description: Console interface.
+ *
+ * Handles console I/O. Defines printk.
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#ifndef _LIB_CONSOLE_H_
+#define _LIB_CONSOLE_H_
+
+#include <mini-os/os.h>
+#include <mini-os/traps.h>
+#include <mini-os/types.h>
+#include <xen/grant_table.h>
+#include <xenbus.h>
+#include <xen/io/console.h>
+#include <stdarg.h>
+
+struct consfront_dev {
+ domid_t dom;
+
+ struct xencons_interface *ring;
+ grant_ref_t ring_ref;
+ evtchn_port_t evtchn;
+
+ char *nodename;
+ char *backend;
+
+ xenbus_event_queue events;
+
+#ifdef HAVE_LIBC
+ int fd;
+#endif
+};
+
+
+
+void print(int direct, const char *fmt, va_list args);
+void printk(const char *fmt, ...);
+void xprintk(const char *fmt, ...);
+
+#define tprintk(_fmt, _args...) printk("[%s] " _fmt, current->name, ##_args)
+
+void xencons_rx(char *buf, unsigned len, struct pt_regs *regs);
+void xencons_tx(void);
+
+void init_console(void);
+void console_print(struct consfront_dev *dev, char *data, int length);
+void fini_console(struct consfront_dev *dev);
+
+/* Low level functions defined in xencons_ring.c */
+extern struct wait_queue_head console_queue;
+struct consfront_dev *xencons_ring_init(void);
+struct consfront_dev *init_consfront(char *_nodename);
+int xencons_ring_send(struct consfront_dev *dev, const char *data, unsigned len);
+int xencons_ring_send_no_notify(struct consfront_dev *dev, const char *data, unsigned len);
+int xencons_ring_avail(struct consfront_dev *dev);
+int xencons_ring_recv(struct consfront_dev *dev, char *data, unsigned len);
+void free_consfront(struct consfront_dev *dev);
+
+#endif /* _LIB_CONSOLE_H_ */
--- /dev/null
+#ifndef _CTYPE_H
+#define _CTYPE_H
+
+#ifdef HAVE_LIBC
+#include_next <ctype.h>
+#else
+/*
+ * NOTE! This ctype does not handle EOF like the standard C
+ * library is required to.
+ */
+
+#define _U 0x01 /* upper */
+#define _L 0x02 /* lower */
+#define _D 0x04 /* digit */
+#define _C 0x08 /* cntrl */
+#define _P 0x10 /* punct */
+#define _S 0x20 /* white space (space/lf/tab) */
+#define _X 0x40 /* hex digit */
+#define _SP 0x80 /* hard space (0x20) */
+
+
+extern unsigned char _ctype[];
+
+#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
+
+#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
+#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
+#define iscntrl(c) ((__ismask(c)&(_C)) != 0)
+#define isdigit(c) ((__ismask(c)&(_D)) != 0)
+#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
+#define islower(c) ((__ismask(c)&(_L)) != 0)
+#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
+#define ispunct(c) ((__ismask(c)&(_P)) != 0)
+#define isspace(c) ((__ismask(c)&(_S)) != 0)
+#define isupper(c) ((__ismask(c)&(_U)) != 0)
+#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
+
+#define isascii(c) (((unsigned char)(c))<=0x7f)
+#define toascii(c) (((unsigned char)(c))&0x7f)
+
+static inline unsigned char __tolower(unsigned char c)
+{
+ if (isupper(c))
+ c -= 'A'-'a';
+ return c;
+}
+
+static inline unsigned char __toupper(unsigned char c)
+{
+ if (islower(c))
+ c -= 'a'-'A';
+ return c;
+}
+
+#define tolower(c) __tolower(c)
+#define toupper(c) __toupper(c)
+
+#endif
+
+#endif
--- /dev/null
+#ifndef _ENDIAN_H_
+#define _ENDIAN_H_
+
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __PDP_ENDIAN 3412
+
+#define ARCH_ENDIAN_H
+/* This will define __BYTE_ORDER for the current arch */
+#include <arch_endian.h>
+#undef ARCH_ENDIAN_H
+
+#include <arch_wordsize.h>
+
+#define BYTE_ORDER __BYTE_ORDER
+#define BIG_ENDIAN __BIG_ENDIAN
+#define LITTLE_ENDIAN __LITTLE_ENDIAN
+
+#endif /* endian.h */
--- /dev/null
+#ifndef _ERR_H
+#define _ERR_H
+
+#include <mini-os/errno.h>
+
+/*
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a dentry
+ * pointer with the same return value.
+ *
+ * This should be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ */
+#define IS_ERR_VALUE(x) ((x) > (unsigned long)-1000L)
+
+static inline void *ERR_PTR(long error)
+{
+ return (void *) error;
+}
+
+static inline long PTR_ERR(const void *ptr)
+{
+ return (long) ptr;
+}
+
+static inline long IS_ERR(const void *ptr)
+{
+ return IS_ERR_VALUE((unsigned long)ptr);
+}
+
+#endif /* _LINUX_ERR_H */
--- /dev/null
+#ifndef _ERRNO_BASE_H
+#define _ERRNO_BASE_H
+
+#define EPERM 1 /* Operation not permitted */
+#define ENOENT 2 /* No such file or directory */
+#define ESRCH 3 /* No such process */
+#define EINTR 4 /* Interrupted system call */
+#define EIO 5 /* I/O error */
+#define ENXIO 6 /* No such device or address */
+#define E2BIG 7 /* Argument list too long */
+#define ENOEXEC 8 /* Exec format error */
+#define EBADF 9 /* Bad file number */
+#define ECHILD 10 /* No child processes */
+#define EAGAIN 11 /* Try again */
+#define ENOMEM 12 /* Out of memory */
+#define EACCES 13 /* Permission denied */
+#define EFAULT 14 /* Bad address */
+#define ENOTBLK 15 /* Block device required */
+#define EBUSY 16 /* Device or resource busy */
+#define EEXIST 17 /* File exists */
+#define EXDEV 18 /* Cross-device link */
+#define ENODEV 19 /* No such device */
+#define ENOTDIR 20 /* Not a directory */
+#define EISDIR 21 /* Is a directory */
+#define EINVAL 22 /* Invalid argument */
+#define ENFILE 23 /* File table overflow */
+#define EMFILE 24 /* Too many open files */
+#define ENOTTY 25 /* Not a typewriter */
+#define ETXTBSY 26 /* Text file busy */
+#define EFBIG 27 /* File too large */
+#define ENOSPC 28 /* No space left on device */
+#define ESPIPE 29 /* Illegal seek */
+#define EROFS 30 /* Read-only file system */
+#define EMLINK 31 /* Too many links */
+#define EPIPE 32 /* Broken pipe */
+#define EDOM 33 /* Math argument out of domain of func */
+#define ERANGE 34 /* Math result not representable */
+
+#endif
--- /dev/null
+#ifndef _ERRNO_H
+#define _ERRNO_H
+
+#include <mini-os/errno-base.h>
+
+typedef int error_t;
+
+#define EDEADLK 35 /* Resource deadlock would occur */
+#define ENAMETOOLONG 36 /* File name too long */
+#define ENOLCK 37 /* No record locks available */
+#define ENOSYS 38 /* Function not implemented */
+#define ENOTEMPTY 39 /* Directory not empty */
+#define ELOOP 40 /* Too many symbolic links encountered */
+#define EWOULDBLOCK EAGAIN /* Operation would block */
+#define ENOMSG 42 /* No message of desired type */
+#define EIDRM 43 /* Identifier removed */
+#define ECHRNG 44 /* Channel number out of range */
+#define EL2NSYNC 45 /* Level 2 not synchronized */
+#define EL3HLT 46 /* Level 3 halted */
+#define EL3RST 47 /* Level 3 reset */
+#define ELNRNG 48 /* Link number out of range */
+#define EUNATCH 49 /* Protocol driver not attached */
+#define ENOCSI 50 /* No CSI structure available */
+#define EL2HLT 51 /* Level 2 halted */
+#define EBADE 52 /* Invalid exchange */
+#define EBADR 53 /* Invalid request descriptor */
+#define EXFULL 54 /* Exchange full */
+#define ENOANO 55 /* No anode */
+#define EBADRQC 56 /* Invalid request code */
+#define EBADSLT 57 /* Invalid slot */
+
+#define EDEADLOCK EDEADLK
+
+#define EBFONT 59 /* Bad font file format */
+#define ENOSTR 60 /* Device not a stream */
+#define ENODATA 61 /* No data available */
+#define ETIME 62 /* Timer expired */
+#define ENOSR 63 /* Out of streams resources */
+#define ENONET 64 /* Machine is not on the network */
+#define ENOPKG 65 /* Package not installed */
+#define EREMOTE 66 /* Object is remote */
+#define ENOLINK 67 /* Link has been severed */
+#define EADV 68 /* Advertise error */
+#define ESRMNT 69 /* Srmount error */
+#define ECOMM 70 /* Communication error on send */
+#define EPROTO 71 /* Protocol error */
+#define EMULTIHOP 72 /* Multihop attempted */
+#define EDOTDOT 73 /* RFS specific error */
+#define EBADMSG 74 /* Not a data message */
+#define EOVERFLOW 75 /* Value too large for defined data type */
+#define ENOTUNIQ 76 /* Name not unique on network */
+#define EBADFD 77 /* File descriptor in bad state */
+#define EREMCHG 78 /* Remote address changed */
+#define ELIBACC 79 /* Can not access a needed shared library */
+#define ELIBBAD 80 /* Accessing a corrupted shared library */
+#define ELIBSCN 81 /* .lib section in a.out corrupted */
+#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
+#define ELIBEXEC 83 /* Cannot exec a shared library directly */
+#define EILSEQ 84 /* Illegal byte sequence */
+#define ERESTART 85 /* Interrupted system call should be restarted */
+#define ESTRPIPE 86 /* Streams pipe error */
+#define EUSERS 87 /* Too many users */
+#define ENOTSOCK 88 /* Socket operation on non-socket */
+#define EDESTADDRREQ 89 /* Destination address required */
+#define EMSGSIZE 90 /* Message too long */
+#define EPROTOTYPE 91 /* Protocol wrong type for socket */
+#define ENOPROTOOPT 92 /* Protocol not available */
+#define EPROTONOSUPPORT 93 /* Protocol not supported */
+#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
+#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
+#define ENOTSUP EOPNOTSUPP
+#define EPFNOSUPPORT 96 /* Protocol family not supported */
+#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
+#define EADDRINUSE 98 /* Address already in use */
+#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
+#define ENETDOWN 100 /* Network is down */
+#define ENETUNREACH 101 /* Network is unreachable */
+#define ENETRESET 102 /* Network dropped connection because of reset */
+#define ECONNABORTED 103 /* Software caused connection abort */
+#define ECONNRESET 104 /* Connection reset by peer */
+#define ENOBUFS 105 /* No buffer space available */
+#define EISCONN 106 /* Transport endpoint is already connected */
+#define ENOTCONN 107 /* Transport endpoint is not connected */
+#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
+#define ETOOMANYREFS 109 /* Too many references: cannot splice */
+#define ETIMEDOUT 110 /* Connection timed out */
+#define ECONNREFUSED 111 /* Connection refused */
+#define EHOSTDOWN 112 /* Host is down */
+#define EHOSTUNREACH 113 /* No route to host */
+#define EALREADY 114 /* Operation already in progress */
+#define EINPROGRESS 115 /* Operation now in progress */
+#define ESTALE 116 /* Stale NFS file handle */
+#define EUCLEAN 117 /* Structure needs cleaning */
+#define ENOTNAM 118 /* Not a XENIX named type file */
+#define ENAVAIL 119 /* No XENIX semaphores available */
+#define EISNAM 120 /* Is a named type file */
+#define EREMOTEIO 121 /* Remote I/O error */
+#define EDQUOT 122 /* Quota exceeded */
+
+#define ENOMEDIUM 123 /* No medium found */
+#define EMEDIUMTYPE 124 /* Wrong medium type */
+#define ECANCELED 125 /* Operation Canceled */
+#define ENOKEY 126 /* Required key not available */
+#define EKEYEXPIRED 127 /* Key has expired */
+#define EKEYREVOKED 128 /* Key has been revoked */
+#define EKEYREJECTED 129 /* Key was rejected by service */
+
+/* for robust mutexes */
+#define EOWNERDEAD 130 /* Owner died */
+#define ENOTRECOVERABLE 131 /* State not recoverable */
+
+
+#define EFTYPE 132 /* Inappropriate file type or format */
+
+#ifdef HAVE_LIBC
+#include <mini-os/sched.h>
+extern int errno;
+#define ERRNO
+#define errno (get_current()->reent._errno)
+#endif
+
+#endif
--- /dev/null
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2005 - Grzegorz Milos - Intel Reseach Cambridge
+ ****************************************************************************
+ *
+ * File: events.h
+ * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
+ * Changes: Grzegorz Milos (gm281@cam.ac.uk)
+ *
+ * Date: Jul 2003, changes Jun 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: Deals with events on the event channels
+ *
+ ****************************************************************************
+ */
+
+#ifndef _EVENTS_H_
+#define _EVENTS_H_
+
+#include<mini-os/traps.h>
+#include<xen/event_channel.h>
+
+typedef void (*evtchn_handler_t)(evtchn_port_t, struct pt_regs *, void *);
+
+/* prototypes */
+void arch_init_events(void);
+
+/* Called by fini_events to close any ports opened by arch-specific code. */
+void arch_unbind_ports(void);
+
+void arch_fini_events(void);
+
+int do_event(evtchn_port_t port, struct pt_regs *regs);
+evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data);
+evtchn_port_t bind_pirq(uint32_t pirq, int will_share, evtchn_handler_t handler, void *data);
+evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler,
+ void *data);
+void unbind_evtchn(evtchn_port_t port);
+void init_events(void);
+int evtchn_alloc_unbound(domid_t pal, evtchn_handler_t handler,
+ void *data, evtchn_port_t *port);
+int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port,
+ evtchn_handler_t handler, void *data,
+ evtchn_port_t *local_port);
+int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size);
+void unbind_all_ports(void);
+
+static inline int notify_remote_via_evtchn(evtchn_port_t port)
+{
+ evtchn_send_t op;
+ op.port = port;
+ return HYPERVISOR_event_channel_op(EVTCHNOP_send, &op);
+}
+
+void fini_events(void);
+
+#endif /* _EVENTS_H_ */
--- /dev/null
+#include <xen/io/kbdif.h>
+#include <xen/io/fbif.h>
+#include <mini-os/semaphore.h>
+#include <mini-os/wait.h>
+
+/* from <linux/input.h> */
+#ifndef BTN_LEFT
+#define BTN_LEFT 0x110
+#endif
+#ifndef BTN_RIGHT
+#define BTN_RIGHT 0x111
+#endif
+#ifndef BTN_MIDDLE
+#define BTN_MIDDLE 0x112
+#endif
+#ifndef KEY_Q
+#define KEY_Q 16
+#endif
+#ifndef KEY_MAX
+#define KEY_MAX 0x1ff
+#endif
+
+
+struct kbdfront_dev;
+struct kbdfront_dev *init_kbdfront(char *nodename, int abs_pointer);
+#ifdef HAVE_LIBC
+int kbdfront_open(struct kbdfront_dev *dev);
+#endif
+
+int kbdfront_receive(struct kbdfront_dev *dev, union xenkbd_in_event *buf, int n);
+extern struct wait_queue_head kbdfront_queue;
+
+void shutdown_kbdfront(struct kbdfront_dev *dev);
+
+
+struct fbfront_dev *init_fbfront(char *nodename, unsigned long *mfns, int width, int height, int depth, int stride, int n);
+#ifdef HAVE_LIBC
+int fbfront_open(struct fbfront_dev *dev);
+#endif
+
+int fbfront_receive(struct fbfront_dev *dev, union xenfb_in_event *buf, int n);
+extern struct wait_queue_head fbfront_queue;
+void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int height);
+void fbfront_resize(struct fbfront_dev *dev, int width, int height, int stride, int depth, int offset);
+
+void shutdown_fbfront(struct fbfront_dev *dev);
--- /dev/null
+#ifndef _I386_FCNTL_H
+#define _I386_FCNTL_H
+
+#ifdef HAVE_LIBC
+#include_next <fcntl.h>
+#else
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+ located on an ext2 file system */
+#define O_ACCMODE 0003
+#define O_RDONLY 00
+#define O_WRONLY 01
+#define O_RDWR 02
+#define O_CREAT 0100 /* not fcntl */
+#define O_EXCL 0200 /* not fcntl */
+#define O_NOCTTY 0400 /* not fcntl */
+#define O_TRUNC 01000 /* not fcntl */
+#define O_APPEND 02000
+#define O_NONBLOCK 04000
+#define O_NDELAY O_NONBLOCK
+#define O_SYNC 010000
+#define FASYNC 020000 /* fcntl, for BSD compatibility */
+#define O_DIRECT 040000 /* direct disk access hint */
+#define O_LARGEFILE 0100000
+#define O_DIRECTORY 0200000 /* must be a directory */
+#define O_NOFOLLOW 0400000 /* don't follow links */
+#define O_NOATIME 01000000
+
+#define F_DUPFD 0 /* dup */
+#define F_GETFD 1 /* get close_on_exec */
+#define F_SETFD 2 /* set/clear close_on_exec */
+#define F_GETFL 3 /* get file->f_flags */
+#define F_SETFL 4 /* set file->f_flags */
+#define F_GETLK 5
+#define F_SETLK 6
+#define F_SETLKW 7
+
+#define F_SETOWN 8 /* for sockets. */
+#define F_GETOWN 9 /* for sockets. */
+#define F_SETSIG 10 /* for sockets. */
+#define F_GETSIG 11 /* for sockets. */
+
+#define F_GETLK64 12 /* using 'struct flock64' */
+#define F_SETLK64 13
+#define F_SETLKW64 14
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK 0
+#define F_WRLCK 1
+#define F_UNLCK 2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK 4 /* or 3 */
+#define F_SHLCK 8 /* or 4 */
+
+/* for leases */
+#define F_INPROGRESS 16
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* or'd with one of the above to prevent
+ blocking */
+#define LOCK_UN 8 /* remove lock */
+
+#define LOCK_MAND 32 /* This is a mandatory flock */
+#define LOCK_READ 64 /* ... Which allows concurrent read operations */
+#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
+#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
+
+/*
+struct flock {
+ short l_type;
+ short l_whence;
+ off_t l_start;
+ off_t l_len;
+ pid_t l_pid;
+};
+
+struct flock64 {
+ short l_type;
+ short l_whence;
+ loff_t l_start;
+ loff_t l_len;
+ pid_t l_pid;
+};
+
+#define F_LINUX_SPECIFIC_BASE 1024
+*/
+
+#endif
+
+int open(const char *path, int flags, ...) asm("open64");
+int fcntl(int fd, int cmd, ...);
+
+#endif
--- /dev/null
+#ifndef __GNTMAP_H__
+#define __GNTMAP_H__
+
+#include <os.h>
+
+/*
+ * Please consider struct gntmap opaque. If instead you choose to disregard
+ * this message, I insist that you keep an eye out for raptors.
+ */
+struct gntmap {
+ int nentries;
+ struct gntmap_entry *entries;
+};
+
+int
+gntmap_set_max_grants(struct gntmap *map, int count);
+
+int
+gntmap_munmap(struct gntmap *map, unsigned long start_address, int count);
+
+void*
+gntmap_map_grant_refs(struct gntmap *map,
+ uint32_t count,
+ uint32_t *domids,
+ int domids_stride,
+ uint32_t *refs,
+ int writable);
+
+void
+gntmap_init(struct gntmap *map);
+
+void
+gntmap_fini(struct gntmap *map);
+
+#endif /* !__GNTMAP_H__ */
--- /dev/null
+#ifndef __GNTTAB_H__
+#define __GNTTAB_H__
+
+#include <xen/grant_table.h>
+
+void init_gnttab(void);
+grant_ref_t gnttab_alloc_and_grant(void **map);
+grant_ref_t gnttab_grant_access(domid_t domid, unsigned long frame,
+ int readonly);
+grant_ref_t gnttab_grant_transfer(domid_t domid, unsigned long pfn);
+unsigned long gnttab_end_transfer(grant_ref_t gref);
+int gnttab_end_access(grant_ref_t ref);
+const char *gnttabop_error(int16_t status);
+void fini_gnttab(void);
+grant_entry_t *arch_init_gnttab(int nr_grant_frames);
+
+#endif /* !__GNTTAB_H__ */
--- /dev/null
+/******************************************************************************
+ * hypervisor.h
+ *
+ * Hypervisor handling.
+ *
+ *
+ * Copyright (c) 2002, K A Fraser
+ * Copyright (c) 2005, Grzegorz Milos
+ * Updates: Aravindh Puthiyaparambil <aravindh.puthiyaparambil@unisys.com>
+ */
+
+#ifndef _HYPERVISOR_H_
+#define _HYPERVISOR_H_
+
+#include <mini-os/types.h>
+#include <xen/xen.h>
+#if defined(__i386__)
+#include <hypercall-x86_32.h>
+#elif defined(__x86_64__)
+#include <hypercall-x86_64.h>
+#elif defined(__arm__) || defined(__aarch64__)
+#include <hypercall-arm.h>
+#else
+#error "Unsupported architecture"
+#endif
+#include <mini-os/traps.h>
+
+/*
+ * a placeholder for the start of day information passed up from the hypervisor
+ */
+union start_info_union
+{
+ start_info_t start_info;
+ char padding[512];
+};
+extern union start_info_union start_info_union;
+#define start_info (start_info_union.start_info)
+
+/* hypervisor.c */
+void force_evtchn_callback(void);
+void do_hypervisor_callback(struct pt_regs *regs);
+void mask_evtchn(uint32_t port);
+void unmask_evtchn(uint32_t port);
+void clear_evtchn(uint32_t port);
+
+extern int in_callback;
+
+#endif /* __HYPERVISOR_H__ */
--- /dev/null
+/**
+ * Copyright (C) 2009 Netronome Systems, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef _IOREMAP_H_
+#define _IOREMAP_H_
+
+void *ioremap(unsigned long phys_addr, unsigned long size);
+void *ioremap_nocache(unsigned long phys_addr, unsigned long size);
+void iounmap(void *virt_addr, unsigned long size);
+
+#endif /* _IOREMAP_H_ */
+
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 indent-tabs-mode:nil -*- */
--- /dev/null
+#ifndef MINIOS_IORW_H
+#define MINIOS_IORW_H
+
+#include <mini-os/types.h>
+
+void iowrite8(volatile void* addr, uint8_t val);
+void iowrite16(volatile void* addr, uint16_t val);
+void iowrite32(volatile void* addr, uint32_t val);
+void iowrite64(volatile void* addr, uint64_t val);
+
+uint8_t ioread8(volatile void* addr);
+uint16_t ioread16(volatile void* addr);
+uint32_t ioread32(volatile void* addr);
+uint64_t ioread64(volatile void* addr);
+
+#endif
--- /dev/null
+#ifndef _KERNEL_H_
+#define _KERNEL_H_
+
+void start_kernel(void);
+void do_exit(void) __attribute__((noreturn));
+void arch_do_exit(void);
+void stop_kernel(void);
+
+#endif /* _KERNEL_H_ */
--- /dev/null
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: lib.h
+ * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
+ * Changes:
+ *
+ * Date: Aug 2003
+ *
+ * Environment: Xen Minimal OS
+ * Description: Random useful library functions, from Linux'
+ * include/linux/kernel.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _LIB_GPL_H_
+#define _LIB_GPL_H_
+
+#ifndef HAVE_LIBC
+/* printing */
+extern unsigned long simple_strtoul(const char *,char **,unsigned int);
+extern long simple_strtol(const char *,char **,unsigned int);
+extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
+extern long long simple_strtoll(const char *,char **,unsigned int);
+
+extern int sprintf(char * buf, const char * fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int vsprintf(char *buf, const char *, va_list)
+ __attribute__ ((format (printf, 2, 0)));
+extern int snprintf(char * buf, size_t size, const char * fmt, ...)
+ __attribute__ ((format (printf, 3, 4)));
+extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+ __attribute__ ((format (printf, 3, 0)));
+extern int scnprintf(char * buf, size_t size, const char * fmt, ...)
+ __attribute__ ((format (printf, 3, 4)));
+extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
+ __attribute__ ((format (printf, 3, 0)));
+extern int sscanf(const char *, const char *, ...)
+ __attribute__ ((format (scanf, 2, 3)));
+extern int vsscanf(const char *, const char *, va_list)
+ __attribute__ ((format (scanf, 2, 0)));
+#endif
+
+#endif /* _LIB_GPL_H_ */
--- /dev/null
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: lib.h
+ * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
+ * Changes:
+ *
+ * Date: Aug 2003
+ *
+ * Environment: Xen Minimal OS
+ * Description: Random useful library functions, contains some freebsd stuff
+ *
+ ****************************************************************************
+ * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
+ ****************************************************************************
+ *
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _LIB_H_
+#define _LIB_H_
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <xen/xen.h>
+#include <xen/event_channel.h>
+#include "gntmap.h"
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+#define BUILD_BUG_ON(cond) ({ _Static_assert(!(cond), "!(" #cond ")"); })
+#define BUILD_BUG_ON_ZERO(cond) \
+ sizeof(struct { _Static_assert(!(cond), "!(" #cond ")"); })
+#else
+#define BUILD_BUG_ON_ZERO(cond) sizeof(struct { int:-!!(cond); })
+#define BUILD_BUG_ON(cond) ((void)BUILD_BUG_ON_ZERO(cond))
+#endif
+
+#ifdef HAVE_LIBC
+#include <sys/queue.h>
+#include <stdio.h>
+#else
+#include <lib-gpl.h>
+#endif
+
+#ifdef HAVE_LIBC
+#include <string.h>
+#else
+/* string and memory manipulation */
+
+/*
+ * From:
+ * @(#)libkern.h 8.1 (Berkeley) 6/10/93
+ * $FreeBSD$
+ */
+int memcmp(const void *b1, const void *b2, size_t len);
+
+char *strcat(char * __restrict, const char * __restrict);
+int strcmp(const char *, const char *);
+char *strcpy(char * __restrict, const char * __restrict);
+
+char *strdup(const char *__restrict);
+
+size_t strlen(const char *);
+
+int strncmp(const char *, const char *, size_t);
+char *strncpy(char * __restrict, const char * __restrict, size_t);
+
+char *strstr(const char *, const char *);
+
+void *memset(void *, int, size_t);
+
+char *strchr(const char *p, int ch);
+char *strrchr(const char *p, int ch);
+
+/* From:
+ * @(#)systm.h 8.7 (Berkeley) 3/29/95
+ * $FreeBSD$
+ */
+void *memcpy(void *to, const void *from, size_t len);
+
+size_t strnlen(const char *, size_t);
+#endif
+
+#include <mini-os/console.h>
+
+#define RAND_MIX 2654435769U
+
+int rand(void);
+
+#include <mini-os/xenbus.h>
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define ASSERT(x) \
+do { \
+ if (!(x)) { \
+ printk("ASSERTION FAILED: %s at %s:%d.\n", \
+ # x , \
+ __FILE__, \
+ __LINE__); \
+ BUG(); \
+ } \
+} while(0)
+
+#define BUG_ON(x) ASSERT(!(x))
+
+/* Consistency check as much as possible. */
+void sanity_check(void);
+
+#ifdef HAVE_LIBC
+enum fd_type {
+ FTYPE_NONE = 0,
+ FTYPE_CONSOLE,
+ FTYPE_FILE,
+ FTYPE_XENBUS,
+ FTYPE_XC,
+ FTYPE_EVTCHN,
+ FTYPE_GNTMAP,
+ FTYPE_SOCKET,
+ FTYPE_TAP,
+ FTYPE_BLK,
+ FTYPE_KBD,
+ FTYPE_FB,
+ FTYPE_MEM,
+ FTYPE_SAVEFILE,
+ FTYPE_TPMFRONT,
+ FTYPE_TPM_TIS,
+};
+
+LIST_HEAD(evtchn_port_list, evtchn_port_info);
+
+struct evtchn_port_info {
+ LIST_ENTRY(evtchn_port_info) list;
+ evtchn_port_t port;
+ unsigned long pending;
+ int bound;
+};
+
+extern struct file {
+ enum fd_type type;
+ union {
+ struct {
+ /* lwIP fd */
+ int fd;
+ } socket;
+ struct {
+ /* FS import fd */
+ int fd;
+ off_t offset;
+ } file;
+ struct {
+ struct evtchn_port_list ports;
+ } evtchn;
+ struct gntmap gntmap;
+ struct {
+ struct netfront_dev *dev;
+ } tap;
+ struct {
+ struct blkfront_dev *dev;
+ off_t offset;
+ } blk;
+ struct {
+ struct kbdfront_dev *dev;
+ } kbd;
+ struct {
+ struct fbfront_dev *dev;
+ } fb;
+ struct {
+ struct consfront_dev *dev;
+ } cons;
+#ifdef CONFIG_TPMFRONT
+ struct {
+ struct tpmfront_dev *dev;
+ int respgot;
+ off_t offset;
+ } tpmfront;
+#endif
+#ifdef CONFIG_TPM_TIS
+ struct {
+ struct tpm_chip *dev;
+ int respgot;
+ off_t offset;
+ } tpm_tis;
+#endif
+#ifdef CONFIG_XENBUS
+ struct {
+ /* To each xenbus FD is associated a queue of watch events for this
+ * FD. */
+ xenbus_event_queue events;
+ } xenbus;
+#endif
+ };
+ int read; /* maybe available for read */
+} files[];
+
+int alloc_fd(enum fd_type type);
+void close_all_files(void);
+extern struct thread *main_thread;
+void sparse(unsigned long data, size_t size);
+#endif
+
+#endif /* _LIB_H_ */
--- /dev/null
+#ifndef _LINUX_TYPES_H_
+#define _LINUX_TYPES_H_
+#include <mini-os/types.h>
+typedef uint64_t __u64;
+#endif /* _LINUX_TYPES_H_ */
--- /dev/null
+/*
+ * lwipopts.h
+ *
+ * Configuration for lwIP running on mini-os
+ *
+ * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
+ */
+
+#ifndef __LWIP_LWIPOPTS_H__
+#define __LWIP_LWIPOPTS_H__
+
+#define SYS_LIGHTWEIGHT_PROT 1
+#define MEM_LIBC_MALLOC 1
+#define LWIP_TIMEVAL_PRIVATE 0
+#define LWIP_DHCP 1
+#define LWIP_COMPAT_SOCKETS 0
+#define LWIP_IGMP 1
+#define LWIP_USE_HEAP_FROM_INTERRUPT 1
+#define MEMP_NUM_SYS_TIMEOUT 10
+#define TCP_SND_BUF 3000
+#define TCP_MSS 1500
+
+#endif /* __LWIP_LWIPOPTS_H__ */
--- /dev/null
+WARNING - DO NOT EDIT THINGS IN THIS DIRECTORY
+----------------------------------------------
+
+These files were obtained elsewhere and should only be updated by
+copying new versions from the source location, as documented below:
+
+bsd-COPYRIGHT
+bsd-sys-queue.h
+bsd-queue.3
+
+ Obtained from the FreeBSD SVN using the following commands:
+ svn co -r 221843 svn://svn.freebsd.org/base/head/sys/sys/
+ svn co -r 221843 svn://svn.freebsd.org/base/head/share/man/man3
+ svn cat -r 221843 http://svn.freebsd.org/base/head/COPYRIGHT >tools/libxl/external/bsd-COPYRIGHT
+
+Exceptions:
+
+README
+
+ This file
+
+bsd-sys-queue-h-seddery
+
+ Script to transform the above into a new namespace.
--- /dev/null
+# $FreeBSD$
+# @(#)COPYRIGHT 8.2 (Berkeley) 3/21/94
+
+The compilation of software known as FreeBSD is distributed under the
+following terms:
+
+Copyright (c) 1992-2011 The FreeBSD Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+The 4.4BSD and 4.4BSD-Lite software is distributed under the following
+terms:
+
+All of the documentation and software included in the 4.4BSD and 4.4BSD-Lite
+Releases is copyrighted by The Regents of the University of California.
+
+Copyright 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
+ The Regents of the University of California. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+This product includes software developed by the University of
+California, Berkeley and its contributors.
+4. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+The Institute of Electrical and Electronics Engineers and the American
+National Standards Committee X3, on Information Processing Systems have
+given us permission to reprint portions of their documentation.
+
+In the following statement, the phrase ``this text'' refers to portions
+of the system documentation.
+
+Portions of this text are reprinted and reproduced in electronic form in
+the second BSD Networking Software Release, from IEEE Std 1003.1-1988, IEEE
+Standard Portable Operating System Interface for Computer Environments
+(POSIX), copyright C 1988 by the Institute of Electrical and Electronics
+Engineers, Inc. In the event of any discrepancy between these versions
+and the original IEEE Standard, the original IEEE Standard is the referee
+document.
+
+In the following statement, the phrase ``This material'' refers to portions
+of the system documentation.
+
+This material is reproduced with permission from American National
+Standards Committee X3, on Information Processing Systems. Computer and
+Business Equipment Manufacturers Association (CBEMA), 311 First St., NW,
+Suite 500, Washington, DC 20001-2178. The developmental work of
+Programming Language C was completed by the X3J11 Technical Committee.
+
+The views and conclusions contained in the software and documentation are
+those of the authors and should not be interpreted as representing official
+policies, either expressed or implied, of the Regents of the University
+of California.
+
+
+NOTE: The copyright of UC Berkeley's Berkeley Software Distribution ("BSD")
+source has been updated. The copyright addendum may be found at
+ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change and is
+included below.
+
+July 22, 1999
+
+To All Licensees, Distributors of Any Version of BSD:
+
+As you know, certain of the Berkeley Software Distribution ("BSD") source
+code files require that further distributions of products containing all or
+portions of the software, acknowledge within their advertising materials
+that such products contain software developed by UC Berkeley and its
+contributors.
+
+Specifically, the provision reads:
+
+" * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors."
+
+Effective immediately, licensees and distributors are no longer required to
+include the acknowledgement within advertising materials. Accordingly, the
+foregoing paragraph of those BSD Unix files containing it is hereby deleted
+in its entirety.
+
+William Hoskins
+Director, Office of Technology Licensing
+University of California, Berkeley
--- /dev/null
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)queue.3 8.2 (Berkeley) 1/24/94
+.\" $FreeBSD$
+.\"
+.Dd May 13, 2011
+.Dt QUEUE 3
+.Os
+.Sh NAME
+.Nm SLIST_EMPTY ,
+.Nm SLIST_ENTRY ,
+.Nm SLIST_FIRST ,
+.Nm SLIST_FOREACH ,
+.Nm SLIST_FOREACH_SAFE ,
+.Nm SLIST_HEAD ,
+.Nm SLIST_HEAD_INITIALIZER ,
+.Nm SLIST_INIT ,
+.Nm SLIST_INSERT_AFTER ,
+.Nm SLIST_INSERT_HEAD ,
+.Nm SLIST_NEXT ,
+.Nm SLIST_REMOVE_AFTER ,
+.Nm SLIST_REMOVE_HEAD ,
+.Nm SLIST_REMOVE ,
+.Nm SLIST_SWAP ,
+.Nm STAILQ_CONCAT ,
+.Nm STAILQ_EMPTY ,
+.Nm STAILQ_ENTRY ,
+.Nm STAILQ_FIRST ,
+.Nm STAILQ_FOREACH ,
+.Nm STAILQ_FOREACH_SAFE ,
+.Nm STAILQ_HEAD ,
+.Nm STAILQ_HEAD_INITIALIZER ,
+.Nm STAILQ_INIT ,
+.Nm STAILQ_INSERT_AFTER ,
+.Nm STAILQ_INSERT_HEAD ,
+.Nm STAILQ_INSERT_TAIL ,
+.Nm STAILQ_LAST ,
+.Nm STAILQ_NEXT ,
+.Nm STAILQ_REMOVE_AFTER ,
+.Nm STAILQ_REMOVE_HEAD ,
+.Nm STAILQ_REMOVE ,
+.Nm STAILQ_SWAP ,
+.Nm LIST_EMPTY ,
+.Nm LIST_ENTRY ,
+.Nm LIST_FIRST ,
+.Nm LIST_FOREACH ,
+.Nm LIST_FOREACH_SAFE ,
+.Nm LIST_HEAD ,
+.Nm LIST_HEAD_INITIALIZER ,
+.Nm LIST_INIT ,
+.Nm LIST_INSERT_AFTER ,
+.Nm LIST_INSERT_BEFORE ,
+.Nm LIST_INSERT_HEAD ,
+.Nm LIST_NEXT ,
+.Nm LIST_REMOVE ,
+.Nm LIST_SWAP ,
+.Nm TAILQ_CONCAT ,
+.Nm TAILQ_EMPTY ,
+.Nm TAILQ_ENTRY ,
+.Nm TAILQ_FIRST ,
+.Nm TAILQ_FOREACH ,
+.Nm TAILQ_FOREACH_SAFE ,
+.Nm TAILQ_FOREACH_REVERSE ,
+.Nm TAILQ_FOREACH_REVERSE_SAFE ,
+.Nm TAILQ_HEAD ,
+.Nm TAILQ_HEAD_INITIALIZER ,
+.Nm TAILQ_INIT ,
+.Nm TAILQ_INSERT_AFTER ,
+.Nm TAILQ_INSERT_BEFORE ,
+.Nm TAILQ_INSERT_HEAD ,
+.Nm TAILQ_INSERT_TAIL ,
+.Nm TAILQ_LAST ,
+.Nm TAILQ_NEXT ,
+.Nm TAILQ_PREV ,
+.Nm TAILQ_REMOVE ,
+.Nm TAILQ_SWAP
+.Nd implementations of singly-linked lists, singly-linked tail queues,
+lists and tail queues
+.Sh SYNOPSIS
+.In sys/queue.h
+.\"
+.Fn SLIST_EMPTY "SLIST_HEAD *head"
+.Fn SLIST_ENTRY "TYPE"
+.Fn SLIST_FIRST "SLIST_HEAD *head"
+.Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
+.Fn SLIST_FOREACH_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
+.Fn SLIST_HEAD "HEADNAME" "TYPE"
+.Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head"
+.Fn SLIST_INIT "SLIST_HEAD *head"
+.Fn SLIST_INSERT_AFTER "TYPE *listelm" "TYPE *elm" "SLIST_ENTRY NAME"
+.Fn SLIST_INSERT_HEAD "SLIST_HEAD *head" "TYPE *elm" "SLIST_ENTRY NAME"
+.Fn SLIST_NEXT "TYPE *elm" "SLIST_ENTRY NAME"
+.Fn SLIST_REMOVE_AFTER "TYPE *elm" "SLIST_ENTRY NAME"
+.Fn SLIST_REMOVE_HEAD "SLIST_HEAD *head" "SLIST_ENTRY NAME"
+.Fn SLIST_REMOVE "SLIST_HEAD *head" "TYPE *elm" "TYPE" "SLIST_ENTRY NAME"
+.Fn SLIST_SWAP "SLIST_HEAD *head1" "SLIST_HEAD *head2" "SLIST_ENTRY NAME"
+.\"
+.Fn STAILQ_CONCAT "STAILQ_HEAD *head1" "STAILQ_HEAD *head2"
+.Fn STAILQ_EMPTY "STAILQ_HEAD *head"
+.Fn STAILQ_ENTRY "TYPE"
+.Fn STAILQ_FIRST "STAILQ_HEAD *head"
+.Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
+.Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
+.Fn STAILQ_HEAD "HEADNAME" "TYPE"
+.Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head"
+.Fn STAILQ_INIT "STAILQ_HEAD *head"
+.Fn STAILQ_INSERT_AFTER "STAILQ_HEAD *head" "TYPE *listelm" "TYPE *elm" "STAILQ_ENTRY NAME"
+.Fn STAILQ_INSERT_HEAD "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
+.Fn STAILQ_INSERT_TAIL "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
+.Fn STAILQ_LAST "STAILQ_HEAD *head" "TYPE" "STAILQ_ENTRY NAME"
+.Fn STAILQ_NEXT "TYPE *elm" "STAILQ_ENTRY NAME"
+.Fn STAILQ_REMOVE_AFTER "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
+.Fn STAILQ_REMOVE_HEAD "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
+.Fn STAILQ_REMOVE "STAILQ_HEAD *head" "TYPE *elm" "TYPE" "STAILQ_ENTRY NAME"
+.Fn STAILQ_SWAP "STAILQ_HEAD *head1" "STAILQ_HEAD *head2" "STAILQ_ENTRY NAME"
+.\"
+.Fn LIST_EMPTY "LIST_HEAD *head"
+.Fn LIST_ENTRY "TYPE"
+.Fn LIST_FIRST "LIST_HEAD *head"
+.Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
+.Fn LIST_FOREACH_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
+.Fn LIST_HEAD "HEADNAME" "TYPE"
+.Fn LIST_HEAD_INITIALIZER "LIST_HEAD head"
+.Fn LIST_INIT "LIST_HEAD *head"
+.Fn LIST_INSERT_AFTER "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
+.Fn LIST_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
+.Fn LIST_INSERT_HEAD "LIST_HEAD *head" "TYPE *elm" "LIST_ENTRY NAME"
+.Fn LIST_NEXT "TYPE *elm" "LIST_ENTRY NAME"
+.Fn LIST_REMOVE "TYPE *elm" "LIST_ENTRY NAME"
+.Fn LIST_SWAP "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME"
+.\"
+.Fn TAILQ_CONCAT "TAILQ_HEAD *head1" "TAILQ_HEAD *head2" "TAILQ_ENTRY NAME"
+.Fn TAILQ_EMPTY "TAILQ_HEAD *head"
+.Fn TAILQ_ENTRY "TYPE"
+.Fn TAILQ_FIRST "TAILQ_HEAD *head"
+.Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
+.Fn TAILQ_FOREACH_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
+.Fn TAILQ_FOREACH_REVERSE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME"
+.Fn TAILQ_FOREACH_REVERSE_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
+.Fn TAILQ_HEAD "HEADNAME" "TYPE"
+.Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head"
+.Fn TAILQ_INIT "TAILQ_HEAD *head"
+.Fn TAILQ_INSERT_AFTER "TAILQ_HEAD *head" "TYPE *listelm" "TYPE *elm" "TAILQ_ENTRY NAME"
+.Fn TAILQ_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "TAILQ_ENTRY NAME"
+.Fn TAILQ_INSERT_HEAD "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
+.Fn TAILQ_INSERT_TAIL "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
+.Fn TAILQ_LAST "TAILQ_HEAD *head" "HEADNAME"
+.Fn TAILQ_NEXT "TYPE *elm" "TAILQ_ENTRY NAME"
+.Fn TAILQ_PREV "TYPE *elm" "HEADNAME" "TAILQ_ENTRY NAME"
+.Fn TAILQ_REMOVE "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
+.Fn TAILQ_SWAP "TAILQ_HEAD *head1" "TAILQ_HEAD *head2" "TYPE" "TAILQ_ENTRY NAME"
+.\"
+.Sh DESCRIPTION
+These macros define and operate on four types of data structures:
+singly-linked lists, singly-linked tail queues, lists, and tail queues.
+All four structures support the following functionality:
+.Bl -enum -compact -offset indent
+.It
+Insertion of a new entry at the head of the list.
+.It
+Insertion of a new entry after any element in the list.
+.It
+O(1) removal of an entry from the head of the list.
+.It
+Forward traversal through the list.
+.It
+Swawpping the contents of two lists.
+.El
+.Pp
+Singly-linked lists are the simplest of the four data structures
+and support only the above functionality.
+Singly-linked lists are ideal for applications with large datasets
+and few or no removals,
+or for implementing a LIFO queue.
+Singly-linked lists add the following functionality:
+.Bl -enum -compact -offset indent
+.It
+O(n) removal of any entry in the list.
+.El
+.Pp
+Singly-linked tail queues add the following functionality:
+.Bl -enum -compact -offset indent
+.It
+Entries can be added at the end of a list.
+.It
+O(n) removal of any entry in the list.
+.It
+They may be concatenated.
+.El
+However:
+.Bl -enum -compact -offset indent
+.It
+All list insertions must specify the head of the list.
+.It
+Each head entry requires two pointers rather than one.
+.It
+Code size is about 15% greater and operations run about 20% slower
+than singly-linked lists.
+.El
+.Pp
+Singly-linked tailqs are ideal for applications with large datasets and
+few or no removals,
+or for implementing a FIFO queue.
+.Pp
+All doubly linked types of data structures (lists and tail queues)
+additionally allow:
+.Bl -enum -compact -offset indent
+.It
+Insertion of a new entry before any element in the list.
+.It
+O(1) removal of any entry in the list.
+.El
+However:
+.Bl -enum -compact -offset indent
+.It
+Each element requires two pointers rather than one.
+.It
+Code size and execution time of operations (except for removal) is about
+twice that of the singly-linked data-structures.
+.El
+.Pp
+Linked lists are the simplest of the doubly linked data structures and support
+only the above functionality over singly-linked lists.
+.Pp
+Tail queues add the following functionality:
+.Bl -enum -compact -offset indent
+.It
+Entries can be added at the end of a list.
+.It
+They may be traversed backwards, from tail to head.
+.It
+They may be concatenated.
+.El
+However:
+.Bl -enum -compact -offset indent
+.It
+All list insertions and removals must specify the head of the list.
+.It
+Each head entry requires two pointers rather than one.
+.It
+Code size is about 15% greater and operations run about 20% slower
+than singly-linked lists.
+.El
+.Pp
+In the macro definitions,
+.Fa TYPE
+is the name of a user defined structure,
+that must contain a field of type
+.Li SLIST_ENTRY ,
+.Li STAILQ_ENTRY ,
+.Li LIST_ENTRY ,
+or
+.Li TAILQ_ENTRY ,
+named
+.Fa NAME .
+The argument
+.Fa HEADNAME
+is the name of a user defined structure that must be declared
+using the macros
+.Li SLIST_HEAD ,
+.Li STAILQ_HEAD ,
+.Li LIST_HEAD ,
+or
+.Li TAILQ_HEAD .
+See the examples below for further explanation of how these
+macros are used.
+.Sh SINGLY-LINKED LISTS
+A singly-linked list is headed by a structure defined by the
+.Nm SLIST_HEAD
+macro.
+This structure contains a single pointer to the first element
+on the list.
+The elements are singly linked for minimum space and pointer manipulation
+overhead at the expense of O(n) removal for arbitrary elements.
+New elements can be added to the list after an existing element or
+at the head of the list.
+An
+.Fa SLIST_HEAD
+structure is declared as follows:
+.Bd -literal -offset indent
+SLIST_HEAD(HEADNAME, TYPE) head;
+.Ed
+.Pp
+where
+.Fa HEADNAME
+is the name of the structure to be defined, and
+.Fa TYPE
+is the type of the elements to be linked into the list.
+A pointer to the head of the list can later be declared as:
+.Bd -literal -offset indent
+struct HEADNAME *headp;
+.Ed
+.Pp
+(The names
+.Li head
+and
+.Li headp
+are user selectable.)
+.Pp
+The macro
+.Nm SLIST_HEAD_INITIALIZER
+evaluates to an initializer for the list
+.Fa head .
+.Pp
+The macro
+.Nm SLIST_EMPTY
+evaluates to true if there are no elements in the list.
+.Pp
+The macro
+.Nm SLIST_ENTRY
+declares a structure that connects the elements in
+the list.
+.Pp
+The macro
+.Nm SLIST_FIRST
+returns the first element in the list or NULL if the list is empty.
+.Pp
+The macro
+.Nm SLIST_FOREACH
+traverses the list referenced by
+.Fa head
+in the forward direction, assigning each element in
+turn to
+.Fa var .
+.Pp
+The macro
+.Nm SLIST_FOREACH_SAFE
+traverses the list referenced by
+.Fa head
+in the forward direction, assigning each element in
+turn to
+.Fa var .
+However, unlike
+.Fn SLIST_FOREACH
+here it is permitted to both remove
+.Fa var
+as well as free it from within the loop safely without interfering with the
+traversal.
+.Pp
+The macro
+.Nm SLIST_INIT
+initializes the list referenced by
+.Fa head .
+.Pp
+The macro
+.Nm SLIST_INSERT_HEAD
+inserts the new element
+.Fa elm
+at the head of the list.
+.Pp
+The macro
+.Nm SLIST_INSERT_AFTER
+inserts the new element
+.Fa elm
+after the element
+.Fa listelm .
+.Pp
+The macro
+.Nm SLIST_NEXT
+returns the next element in the list.
+.Pp
+The macro
+.Nm SLIST_REMOVE_AFTER
+removes the element after
+.Fa elm
+from the list. Unlike
+.Fa SLIST_REMOVE ,
+this macro does not traverse the entire list.
+.Pp
+The macro
+.Nm SLIST_REMOVE_HEAD
+removes the element
+.Fa elm
+from the head of the list.
+For optimum efficiency,
+elements being removed from the head of the list should explicitly use
+this macro instead of the generic
+.Fa SLIST_REMOVE
+macro.
+.Pp
+The macro
+.Nm SLIST_REMOVE
+removes the element
+.Fa elm
+from the list.
+.Pp
+The macro
+.Nm SLIST_SWAP
+swaps the contents of
+.Fa head1
+and
+.Fa head2 .
+.Sh SINGLY-LINKED LIST EXAMPLE
+.Bd -literal
+SLIST_HEAD(slisthead, entry) head =
+ SLIST_HEAD_INITIALIZER(head);
+struct slisthead *headp; /* Singly-linked List head. */
+struct entry {
+ ...
+ SLIST_ENTRY(entry) entries; /* Singly-linked List. */
+ ...
+} *n1, *n2, *n3, *np;
+
+SLIST_INIT(&head); /* Initialize the list. */
+
+n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
+SLIST_INSERT_HEAD(&head, n1, entries);
+
+n2 = malloc(sizeof(struct entry)); /* Insert after. */
+SLIST_INSERT_AFTER(n1, n2, entries);
+
+SLIST_REMOVE(&head, n2, entry, entries);/* Deletion. */
+free(n2);
+
+n3 = SLIST_FIRST(&head);
+SLIST_REMOVE_HEAD(&head, entries); /* Deletion from the head. */
+free(n3);
+ /* Forward traversal. */
+SLIST_FOREACH(np, &head, entries)
+ np-> ...
+ /* Safe forward traversal. */
+SLIST_FOREACH_SAFE(np, &head, entries, np_temp) {
+ np->do_stuff();
+ ...
+ SLIST_REMOVE(&head, np, entry, entries);
+ free(np);
+}
+
+while (!SLIST_EMPTY(&head)) { /* List Deletion. */
+ n1 = SLIST_FIRST(&head);
+ SLIST_REMOVE_HEAD(&head, entries);
+ free(n1);
+}
+.Ed
+.Sh SINGLY-LINKED TAIL QUEUES
+A singly-linked tail queue is headed by a structure defined by the
+.Nm STAILQ_HEAD
+macro.
+This structure contains a pair of pointers,
+one to the first element in the tail queue and the other to
+the last element in the tail queue.
+The elements are singly linked for minimum space and pointer
+manipulation overhead at the expense of O(n) removal for arbitrary
+elements.
+New elements can be added to the tail queue after an existing element,
+at the head of the tail queue, or at the end of the tail queue.
+A
+.Fa STAILQ_HEAD
+structure is declared as follows:
+.Bd -literal -offset indent
+STAILQ_HEAD(HEADNAME, TYPE) head;
+.Ed
+.Pp
+where
+.Li HEADNAME
+is the name of the structure to be defined, and
+.Li TYPE
+is the type of the elements to be linked into the tail queue.
+A pointer to the head of the tail queue can later be declared as:
+.Bd -literal -offset indent
+struct HEADNAME *headp;
+.Ed
+.Pp
+(The names
+.Li head
+and
+.Li headp
+are user selectable.)
+.Pp
+The macro
+.Nm STAILQ_HEAD_INITIALIZER
+evaluates to an initializer for the tail queue
+.Fa head .
+.Pp
+The macro
+.Nm STAILQ_CONCAT
+concatenates the tail queue headed by
+.Fa head2
+onto the end of the one headed by
+.Fa head1
+removing all entries from the former.
+.Pp
+The macro
+.Nm STAILQ_EMPTY
+evaluates to true if there are no items on the tail queue.
+.Pp
+The macro
+.Nm STAILQ_ENTRY
+declares a structure that connects the elements in
+the tail queue.
+.Pp
+The macro
+.Nm STAILQ_FIRST
+returns the first item on the tail queue or NULL if the tail queue
+is empty.
+.Pp
+The macro
+.Nm STAILQ_FOREACH
+traverses the tail queue referenced by
+.Fa head
+in the forward direction, assigning each element
+in turn to
+.Fa var .
+.Pp
+The macro
+.Nm STAILQ_FOREACH_SAFE
+traverses the tail queue referenced by
+.Fa head
+in the forward direction, assigning each element
+in turn to
+.Fa var .
+However, unlike
+.Fn STAILQ_FOREACH
+here it is permitted to both remove
+.Fa var
+as well as free it from within the loop safely without interfering with the
+traversal.
+.Pp
+The macro
+.Nm STAILQ_INIT
+initializes the tail queue referenced by
+.Fa head .
+.Pp
+The macro
+.Nm STAILQ_INSERT_HEAD
+inserts the new element
+.Fa elm
+at the head of the tail queue.
+.Pp
+The macro
+.Nm STAILQ_INSERT_TAIL
+inserts the new element
+.Fa elm
+at the end of the tail queue.
+.Pp
+The macro
+.Nm STAILQ_INSERT_AFTER
+inserts the new element
+.Fa elm
+after the element
+.Fa listelm .
+.Pp
+The macro
+.Nm STAILQ_LAST
+returns the last item on the tail queue.
+If the tail queue is empty the return value is
+.Dv NULL .
+.Pp
+The macro
+.Nm STAILQ_NEXT
+returns the next item on the tail queue, or NULL this item is the last.
+.Pp
+The macro
+.Nm STAILQ_REMOVE_AFTER
+removes the element after
+.Fa elm
+from the tail queue. Unlike
+.Fa STAILQ_REMOVE ,
+this macro does not traverse the entire tail queue.
+.Pp
+The macro
+.Nm STAILQ_REMOVE_HEAD
+removes the element at the head of the tail queue.
+For optimum efficiency,
+elements being removed from the head of the tail queue should
+use this macro explicitly rather than the generic
+.Fa STAILQ_REMOVE
+macro.
+.Pp
+The macro
+.Nm STAILQ_REMOVE
+removes the element
+.Fa elm
+from the tail queue.
+.Pp
+The macro
+.Nm STAILQ_SWAP
+swaps the contents of
+.Fa head1
+and
+.Fa head2 .
+.Sh SINGLY-LINKED TAIL QUEUE EXAMPLE
+.Bd -literal
+STAILQ_HEAD(stailhead, entry) head =
+ STAILQ_HEAD_INITIALIZER(head);
+struct stailhead *headp; /* Singly-linked tail queue head. */
+struct entry {
+ ...
+ STAILQ_ENTRY(entry) entries; /* Tail queue. */
+ ...
+} *n1, *n2, *n3, *np;
+
+STAILQ_INIT(&head); /* Initialize the queue. */
+
+n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
+STAILQ_INSERT_HEAD(&head, n1, entries);
+
+n1 = malloc(sizeof(struct entry)); /* Insert at the tail. */
+STAILQ_INSERT_TAIL(&head, n1, entries);
+
+n2 = malloc(sizeof(struct entry)); /* Insert after. */
+STAILQ_INSERT_AFTER(&head, n1, n2, entries);
+ /* Deletion. */
+STAILQ_REMOVE(&head, n2, entry, entries);
+free(n2);
+ /* Deletion from the head. */
+n3 = STAILQ_FIRST(&head);
+STAILQ_REMOVE_HEAD(&head, entries);
+free(n3);
+ /* Forward traversal. */
+STAILQ_FOREACH(np, &head, entries)
+ np-> ...
+ /* Safe forward traversal. */
+STAILQ_FOREACH_SAFE(np, &head, entries, np_temp) {
+ np->do_stuff();
+ ...
+ STAILQ_REMOVE(&head, np, entry, entries);
+ free(np);
+}
+ /* TailQ Deletion. */
+while (!STAILQ_EMPTY(&head)) {
+ n1 = STAILQ_FIRST(&head);
+ STAILQ_REMOVE_HEAD(&head, entries);
+ free(n1);
+}
+ /* Faster TailQ Deletion. */
+n1 = STAILQ_FIRST(&head);
+while (n1 != NULL) {
+ n2 = STAILQ_NEXT(n1, entries);
+ free(n1);
+ n1 = n2;
+}
+STAILQ_INIT(&head);
+.Ed
+.Sh LISTS
+A list is headed by a structure defined by the
+.Nm LIST_HEAD
+macro.
+This structure contains a single pointer to the first element
+on the list.
+The elements are doubly linked so that an arbitrary element can be
+removed without traversing the list.
+New elements can be added to the list after an existing element,
+before an existing element, or at the head of the list.
+A
+.Fa LIST_HEAD
+structure is declared as follows:
+.Bd -literal -offset indent
+LIST_HEAD(HEADNAME, TYPE) head;
+.Ed
+.Pp
+where
+.Fa HEADNAME
+is the name of the structure to be defined, and
+.Fa TYPE
+is the type of the elements to be linked into the list.
+A pointer to the head of the list can later be declared as:
+.Bd -literal -offset indent
+struct HEADNAME *headp;
+.Ed
+.Pp
+(The names
+.Li head
+and
+.Li headp
+are user selectable.)
+.Pp
+The macro
+.Nm LIST_HEAD_INITIALIZER
+evaluates to an initializer for the list
+.Fa head .
+.Pp
+The macro
+.Nm LIST_EMPTY
+evaluates to true if there are no elements in the list.
+.Pp
+The macro
+.Nm LIST_ENTRY
+declares a structure that connects the elements in
+the list.
+.Pp
+The macro
+.Nm LIST_FIRST
+returns the first element in the list or NULL if the list
+is empty.
+.Pp
+The macro
+.Nm LIST_FOREACH
+traverses the list referenced by
+.Fa head
+in the forward direction, assigning each element in turn to
+.Fa var .
+.Pp
+The macro
+.Nm LIST_FOREACH_SAFE
+traverses the list referenced by
+.Fa head
+in the forward direction, assigning each element in turn to
+.Fa var .
+However, unlike
+.Fn LIST_FOREACH
+here it is permitted to both remove
+.Fa var
+as well as free it from within the loop safely without interfering with the
+traversal.
+.Pp
+The macro
+.Nm LIST_INIT
+initializes the list referenced by
+.Fa head .
+.Pp
+The macro
+.Nm LIST_INSERT_HEAD
+inserts the new element
+.Fa elm
+at the head of the list.
+.Pp
+The macro
+.Nm LIST_INSERT_AFTER
+inserts the new element
+.Fa elm
+after the element
+.Fa listelm .
+.Pp
+The macro
+.Nm LIST_INSERT_BEFORE
+inserts the new element
+.Fa elm
+before the element
+.Fa listelm .
+.Pp
+The macro
+.Nm LIST_NEXT
+returns the next element in the list, or NULL if this is the last.
+.Pp
+The macro
+.Nm LIST_REMOVE
+removes the element
+.Fa elm
+from the list.
+.Pp
+The macro
+.Nm LIST_SWAP
+swaps the contents of
+.Fa head1
+and
+.Fa head2 .
+.Sh LIST EXAMPLE
+.Bd -literal
+LIST_HEAD(listhead, entry) head =
+ LIST_HEAD_INITIALIZER(head);
+struct listhead *headp; /* List head. */
+struct entry {
+ ...
+ LIST_ENTRY(entry) entries; /* List. */
+ ...
+} *n1, *n2, *n3, *np, *np_temp;
+
+LIST_INIT(&head); /* Initialize the list. */
+
+n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
+LIST_INSERT_HEAD(&head, n1, entries);
+
+n2 = malloc(sizeof(struct entry)); /* Insert after. */
+LIST_INSERT_AFTER(n1, n2, entries);
+
+n3 = malloc(sizeof(struct entry)); /* Insert before. */
+LIST_INSERT_BEFORE(n2, n3, entries);
+
+LIST_REMOVE(n2, entries); /* Deletion. */
+free(n2);
+ /* Forward traversal. */
+LIST_FOREACH(np, &head, entries)
+ np-> ...
+
+ /* Safe forward traversal. */
+LIST_FOREACH_SAFE(np, &head, entries, np_temp) {
+ np->do_stuff();
+ ...
+ LIST_REMOVE(np, entries);
+ free(np);
+}
+
+while (!LIST_EMPTY(&head)) { /* List Deletion. */
+ n1 = LIST_FIRST(&head);
+ LIST_REMOVE(n1, entries);
+ free(n1);
+}
+
+n1 = LIST_FIRST(&head); /* Faster List Deletion. */
+while (n1 != NULL) {
+ n2 = LIST_NEXT(n1, entries);
+ free(n1);
+ n1 = n2;
+}
+LIST_INIT(&head);
+.Ed
+.Sh TAIL QUEUES
+A tail queue is headed by a structure defined by the
+.Nm TAILQ_HEAD
+macro.
+This structure contains a pair of pointers,
+one to the first element in the tail queue and the other to
+the last element in the tail queue.
+The elements are doubly linked so that an arbitrary element can be
+removed without traversing the tail queue.
+New elements can be added to the tail queue after an existing element,
+before an existing element, at the head of the tail queue,
+or at the end of the tail queue.
+A
+.Fa TAILQ_HEAD
+structure is declared as follows:
+.Bd -literal -offset indent
+TAILQ_HEAD(HEADNAME, TYPE) head;
+.Ed
+.Pp
+where
+.Li HEADNAME
+is the name of the structure to be defined, and
+.Li TYPE
+is the type of the elements to be linked into the tail queue.
+A pointer to the head of the tail queue can later be declared as:
+.Bd -literal -offset indent
+struct HEADNAME *headp;
+.Ed
+.Pp
+(The names
+.Li head
+and
+.Li headp
+are user selectable.)
+.Pp
+The macro
+.Nm TAILQ_HEAD_INITIALIZER
+evaluates to an initializer for the tail queue
+.Fa head .
+.Pp
+The macro
+.Nm TAILQ_CONCAT
+concatenates the tail queue headed by
+.Fa head2
+onto the end of the one headed by
+.Fa head1
+removing all entries from the former.
+.Pp
+The macro
+.Nm TAILQ_EMPTY
+evaluates to true if there are no items on the tail queue.
+.Pp
+The macro
+.Nm TAILQ_ENTRY
+declares a structure that connects the elements in
+the tail queue.
+.Pp
+The macro
+.Nm TAILQ_FIRST
+returns the first item on the tail queue or NULL if the tail queue
+is empty.
+.Pp
+The macro
+.Nm TAILQ_FOREACH
+traverses the tail queue referenced by
+.Fa head
+in the forward direction, assigning each element in turn to
+.Fa var .
+.Fa var
+is set to
+.Dv NULL
+if the loop completes normally, or if there were no elements.
+.Pp
+The macro
+.Nm TAILQ_FOREACH_REVERSE
+traverses the tail queue referenced by
+.Fa head
+in the reverse direction, assigning each element in turn to
+.Fa var .
+.Pp
+The macros
+.Nm TAILQ_FOREACH_SAFE
+and
+.Nm TAILQ_FOREACH_REVERSE_SAFE
+traverse the list referenced by
+.Fa head
+in the forward or reverse direction respectively,
+assigning each element in turn to
+.Fa var .
+However, unlike their unsafe counterparts,
+.Nm TAILQ_FOREACH
+and
+.Nm TAILQ_FOREACH_REVERSE
+permit to both remove
+.Fa var
+as well as free it from within the loop safely without interfering with the
+traversal.
+.Pp
+The macro
+.Nm TAILQ_INIT
+initializes the tail queue referenced by
+.Fa head .
+.Pp
+The macro
+.Nm TAILQ_INSERT_HEAD
+inserts the new element
+.Fa elm
+at the head of the tail queue.
+.Pp
+The macro
+.Nm TAILQ_INSERT_TAIL
+inserts the new element
+.Fa elm
+at the end of the tail queue.
+.Pp
+The macro
+.Nm TAILQ_INSERT_AFTER
+inserts the new element
+.Fa elm
+after the element
+.Fa listelm .
+.Pp
+The macro
+.Nm TAILQ_INSERT_BEFORE
+inserts the new element
+.Fa elm
+before the element
+.Fa listelm .
+.Pp
+The macro
+.Nm TAILQ_LAST
+returns the last item on the tail queue.
+If the tail queue is empty the return value is
+.Dv NULL .
+.Pp
+The macro
+.Nm TAILQ_NEXT
+returns the next item on the tail queue, or NULL if this item is the last.
+.Pp
+The macro
+.Nm TAILQ_PREV
+returns the previous item on the tail queue, or NULL if this item
+is the first.
+.Pp
+The macro
+.Nm TAILQ_REMOVE
+removes the element
+.Fa elm
+from the tail queue.
+.Pp
+The macro
+.Nm TAILQ_SWAP
+swaps the contents of
+.Fa head1
+and
+.Fa head2 .
+.Sh TAIL QUEUE EXAMPLE
+.Bd -literal
+TAILQ_HEAD(tailhead, entry) head =
+ TAILQ_HEAD_INITIALIZER(head);
+struct tailhead *headp; /* Tail queue head. */
+struct entry {
+ ...
+ TAILQ_ENTRY(entry) entries; /* Tail queue. */
+ ...
+} *n1, *n2, *n3, *np;
+
+TAILQ_INIT(&head); /* Initialize the queue. */
+
+n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
+TAILQ_INSERT_HEAD(&head, n1, entries);
+
+n1 = malloc(sizeof(struct entry)); /* Insert at the tail. */
+TAILQ_INSERT_TAIL(&head, n1, entries);
+
+n2 = malloc(sizeof(struct entry)); /* Insert after. */
+TAILQ_INSERT_AFTER(&head, n1, n2, entries);
+
+n3 = malloc(sizeof(struct entry)); /* Insert before. */
+TAILQ_INSERT_BEFORE(n2, n3, entries);
+
+TAILQ_REMOVE(&head, n2, entries); /* Deletion. */
+free(n2);
+ /* Forward traversal. */
+TAILQ_FOREACH(np, &head, entries)
+ np-> ...
+ /* Safe forward traversal. */
+TAILQ_FOREACH_SAFE(np, &head, entries, np_temp) {
+ np->do_stuff();
+ ...
+ TAILQ_REMOVE(&head, np, entries);
+ free(np);
+}
+ /* Reverse traversal. */
+TAILQ_FOREACH_REVERSE(np, &head, tailhead, entries)
+ np-> ...
+ /* TailQ Deletion. */
+while (!TAILQ_EMPTY(&head)) {
+ n1 = TAILQ_FIRST(&head);
+ TAILQ_REMOVE(&head, n1, entries);
+ free(n1);
+}
+ /* Faster TailQ Deletion. */
+n1 = TAILQ_FIRST(&head);
+while (n1 != NULL) {
+ n2 = TAILQ_NEXT(n1, entries);
+ free(n1);
+ n1 = n2;
+}
+TAILQ_INIT(&head);
+.Ed
+.Sh SEE ALSO
+.Xr tree 3
+.Sh HISTORY
+The
+.Nm queue
+functions first appeared in
+.Bx 4.4 .
--- /dev/null
+#!/usr/bin/perl -p
+#
+# This script is part of the Xen build system. It has a very
+# permissive licence to avoid complicating the licence of the
+# generated header file and to allow this seddery to be reused by
+# other projects.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this individual file (the "Software"), to deal
+# in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute,
+# sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the
+# following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+# Copyright (C) 2011 Citrix Ltd
+
+our $namespace, $ucnamespace;
+
+BEGIN {
+ die unless @ARGV;
+ $namespace = pop @ARGV;
+ $namespace =~ s/^--prefix=// or die;
+ $ucnamespace = uc $namespace;
+
+ print <<END or die $!;
+/*
+ * DO NOT EDIT THIS FILE
+ *
+ * Generated automatically by bsd-sys-queue-h-seddery to
+ * - introduce ${ucnamespace}_ and ${namespace}_ namespace prefixes
+ * - turn "struct type" into "type" so that type arguments
+ * to the macros are type names not struct tags
+ * - remove the reference to sys/cdefs.h, which is not needed
+ *
+ * The purpose of this seddery is to allow the resulting file to be
+ * freely included by software which might also want to include other
+ * list macros; to make it usable when struct tags are not being used
+ * or not known; to make it more portable.
+ */
+END
+}
+
+s/\b( _SYS_QUEUE |
+ SLIST | LIST | STAILQ | TAILQ | QUEUE
+ )/${ucnamespace}_$1/xg;
+
+s/\b( TRACEBUF | TRASHIT |
+ QMD_
+ )/${ucnamespace}__$1/xg;
+
+s/\b(
+ qm_
+ )/${namespace}__$1/xg;
+
+s/\b struct \s+ type \b/type/xg;
+
+s,^\#include.*sys/cdefs.*,/* $& */,xg;
+
+s/\b( NULL )/0/xg;
--- /dev/null
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+#include <sys/cdefs.h>
+
+/*
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ * SLIST LIST STAILQ TAILQ
+ * _HEAD + + + +
+ * _HEAD_INITIALIZER + + + +
+ * _ENTRY + + + +
+ * _INIT + + + +
+ * _EMPTY + + + +
+ * _FIRST + + + +
+ * _NEXT + + + +
+ * _PREV - - - +
+ * _LAST - - + +
+ * _FOREACH + + + +
+ * _FOREACH_SAFE + + + +
+ * _FOREACH_REVERSE - - - +
+ * _FOREACH_REVERSE_SAFE - - - +
+ * _INSERT_HEAD + + + +
+ * _INSERT_BEFORE - + - +
+ * _INSERT_AFTER + + + +
+ * _INSERT_TAIL - - + +
+ * _CONCAT - - + +
+ * _REMOVE_AFTER + - + -
+ * _REMOVE_HEAD + - + -
+ * _REMOVE + + + +
+ * _SWAP + + + +
+ *
+ */
+#ifdef QUEUE_MACRO_DEBUG
+/* Store the last 2 places the queue element or head was altered */
+struct qm_trace {
+ char * lastfile;
+ int lastline;
+ char * prevfile;
+ int prevline;
+};
+
+#define TRACEBUF struct qm_trace trace;
+#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
+#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
+
+#define QMD_TRACE_HEAD(head) do { \
+ (head)->trace.prevline = (head)->trace.lastline; \
+ (head)->trace.prevfile = (head)->trace.lastfile; \
+ (head)->trace.lastline = __LINE__; \
+ (head)->trace.lastfile = __FILE__; \
+} while (0)
+
+#define QMD_TRACE_ELEM(elem) do { \
+ (elem)->trace.prevline = (elem)->trace.lastline; \
+ (elem)->trace.prevfile = (elem)->trace.lastfile; \
+ (elem)->trace.lastline = __LINE__; \
+ (elem)->trace.lastfile = __FILE__; \
+} while (0)
+
+#else
+#define QMD_TRACE_ELEM(elem)
+#define QMD_TRACE_HEAD(head)
+#define QMD_SAVELINK(name, link)
+#define TRACEBUF
+#define TRASHIT(x)
+#endif /* QUEUE_MACRO_DEBUG */
+
+/*
+ * Singly-linked List declarations.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+
+#define SLIST_FIRST(head) ((head)->slh_first)
+
+#define SLIST_FOREACH(var, head, field) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var); \
+ (var) = SLIST_NEXT((var), field))
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
+ for ((varp) = &SLIST_FIRST((head)); \
+ ((var) = *(varp)) != NULL; \
+ (varp) = &SLIST_NEXT((var), field))
+
+#define SLIST_INIT(head) do { \
+ SLIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
+ SLIST_NEXT((slistelm), field) = (elm); \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
+ SLIST_FIRST((head)) = (elm); \
+} while (0)
+
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
+ if (SLIST_FIRST((head)) == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = SLIST_FIRST((head)); \
+ while (SLIST_NEXT(curelm, field) != (elm)) \
+ curelm = SLIST_NEXT(curelm, field); \
+ SLIST_REMOVE_AFTER(curelm, field); \
+ } \
+ TRASHIT(*oldnext); \
+} while (0)
+
+#define SLIST_REMOVE_AFTER(elm, field) do { \
+ SLIST_NEXT(elm, field) = \
+ SLIST_NEXT(SLIST_NEXT(elm, field), field); \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
+} while (0)
+
+#define SLIST_SWAP(head1, head2, type) do { \
+ struct type *swap_first = SLIST_FIRST(head1); \
+ SLIST_FIRST(head1) = SLIST_FIRST(head2); \
+ SLIST_FIRST(head2) = swap_first; \
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first;/* first element */ \
+ struct type **stqh_last;/* addr of last next element */ \
+}
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (0)
+
+#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
+
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for((var) = STAILQ_FIRST((head)); \
+ (var); \
+ (var) = STAILQ_NEXT((var), field))
+
+
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = STAILQ_FIRST((head)); \
+ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define STAILQ_INIT(head) do { \
+ STAILQ_FIRST((head)) = NULL; \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_NEXT((tqelm), field) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_FIRST((head)) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ STAILQ_NEXT((elm), field) = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+} while (0)
+
+#define STAILQ_LAST(head, type, field) \
+ (STAILQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *)(void *) \
+ ((char *)((head)->stqh_last) - __offsetof(struct type, field))))
+
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
+ if (STAILQ_FIRST((head)) == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = STAILQ_FIRST((head)); \
+ while (STAILQ_NEXT(curelm, field) != (elm)) \
+ curelm = STAILQ_NEXT(curelm, field); \
+ STAILQ_REMOVE_AFTER(head, curelm, field); \
+ } \
+ TRASHIT(*oldnext); \
+} while (0)
+
+#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
+ if ((STAILQ_NEXT(elm, field) = \
+ STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+} while (0)
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if ((STAILQ_FIRST((head)) = \
+ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_SWAP(head1, head2, type) do { \
+ struct type *swap_first = STAILQ_FIRST(head1); \
+ struct type **swap_last = (head1)->stqh_last; \
+ STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_FIRST(head2) = swap_first; \
+ (head2)->stqh_last = swap_last; \
+ if (STAILQ_EMPTY(head1)) \
+ (head1)->stqh_last = &STAILQ_FIRST(head1); \
+ if (STAILQ_EMPTY(head2)) \
+ (head2)->stqh_last = &STAILQ_FIRST(head2); \
+} while (0)
+
+
+/*
+ * List declarations.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+
+#if (defined(_KERNEL) && defined(INVARIANTS))
+#define QMD_LIST_CHECK_HEAD(head, field) do { \
+ if (LIST_FIRST((head)) != NULL && \
+ LIST_FIRST((head))->field.le_prev != \
+ &LIST_FIRST((head))) \
+ panic("Bad list head %p first->prev != head", (head)); \
+} while (0)
+
+#define QMD_LIST_CHECK_NEXT(elm, field) do { \
+ if (LIST_NEXT((elm), field) != NULL && \
+ LIST_NEXT((elm), field)->field.le_prev != \
+ &((elm)->field.le_next)) \
+ panic("Bad link elm %p next->prev != elm", (elm)); \
+} while (0)
+
+#define QMD_LIST_CHECK_PREV(elm, field) do { \
+ if (*(elm)->field.le_prev != (elm)) \
+ panic("Bad link elm %p prev->next != elm", (elm)); \
+} while (0)
+#else
+#define QMD_LIST_CHECK_HEAD(head, field)
+#define QMD_LIST_CHECK_NEXT(elm, field)
+#define QMD_LIST_CHECK_PREV(elm, field)
+#endif /* (_KERNEL && INVARIANTS) */
+
+#define LIST_EMPTY(head) ((head)->lh_first == NULL)
+
+#define LIST_FIRST(head) ((head)->lh_first)
+
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = LIST_FIRST((head)); \
+ (var); \
+ (var) = LIST_NEXT((var), field))
+
+#define LIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = LIST_FIRST((head)); \
+ (var) && ((tvar) = LIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define LIST_INIT(head) do { \
+ LIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ QMD_LIST_CHECK_NEXT(listelm, field); \
+ if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+ LIST_NEXT((listelm), field)->field.le_prev = \
+ &LIST_NEXT((elm), field); \
+ LIST_NEXT((listelm), field) = (elm); \
+ (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
+} while (0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ QMD_LIST_CHECK_PREV(listelm, field); \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ LIST_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ QMD_LIST_CHECK_HEAD((head), field); \
+ if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
+ LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+ LIST_FIRST((head)) = (elm); \
+ (elm)->field.le_prev = &LIST_FIRST((head)); \
+} while (0)
+
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_REMOVE(elm, field) do { \
+ QMD_SAVELINK(oldnext, (elm)->field.le_next); \
+ QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
+ QMD_LIST_CHECK_NEXT(elm, field); \
+ QMD_LIST_CHECK_PREV(elm, field); \
+ if (LIST_NEXT((elm), field) != NULL) \
+ LIST_NEXT((elm), field)->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = LIST_NEXT((elm), field); \
+ TRASHIT(*oldnext); \
+ TRASHIT(*oldprev); \
+} while (0)
+
+#define LIST_SWAP(head1, head2, type, field) do { \
+ struct type *swap_tmp = LIST_FIRST((head1)); \
+ LIST_FIRST((head1)) = LIST_FIRST((head2)); \
+ LIST_FIRST((head2)) = swap_tmp; \
+ if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
+ swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
+ if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
+ swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+ TRACEBUF \
+}
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+ TRACEBUF \
+}
+
+/*
+ * Tail queue functions.
+ */
+#if (defined(_KERNEL) && defined(INVARIANTS))
+#define QMD_TAILQ_CHECK_HEAD(head, field) do { \
+ if (!TAILQ_EMPTY(head) && \
+ TAILQ_FIRST((head))->field.tqe_prev != \
+ &TAILQ_FIRST((head))) \
+ panic("Bad tailq head %p first->prev != head", (head)); \
+} while (0)
+
+#define QMD_TAILQ_CHECK_TAIL(head, field) do { \
+ if (*(head)->tqh_last != NULL) \
+ panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
+} while (0)
+
+#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
+ if (TAILQ_NEXT((elm), field) != NULL && \
+ TAILQ_NEXT((elm), field)->field.tqe_prev != \
+ &((elm)->field.tqe_next)) \
+ panic("Bad link elm %p next->prev != elm", (elm)); \
+} while (0)
+
+#define QMD_TAILQ_CHECK_PREV(elm, field) do { \
+ if (*(elm)->field.tqe_prev != (elm)) \
+ panic("Bad link elm %p prev->next != elm", (elm)); \
+} while (0)
+#else
+#define QMD_TAILQ_CHECK_HEAD(head, field)
+#define QMD_TAILQ_CHECK_TAIL(head, headname)
+#define QMD_TAILQ_CHECK_NEXT(elm, field)
+#define QMD_TAILQ_CHECK_PREV(elm, field)
+#endif /* (_KERNEL && INVARIANTS) */
+
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ QMD_TRACE_HEAD(head1); \
+ QMD_TRACE_HEAD(head2); \
+ } \
+} while (0)
+
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var); \
+ (var) = TAILQ_NEXT((var), field))
+
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var); \
+ (var) = TAILQ_PREV((var), headname, field))
+
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
+ (var) = (tvar))
+
+#define TAILQ_INIT(head) do { \
+ TAILQ_FIRST((head)) = NULL; \
+ (head)->tqh_last = &TAILQ_FIRST((head)); \
+ QMD_TRACE_HEAD(head); \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ QMD_TAILQ_CHECK_NEXT(listelm, field); \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else { \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_HEAD(head); \
+ } \
+ TAILQ_NEXT((listelm), field) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+ QMD_TRACE_ELEM(&listelm->field); \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ QMD_TAILQ_CHECK_PREV(listelm, field); \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ TAILQ_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+ QMD_TRACE_ELEM(&listelm->field); \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ QMD_TAILQ_CHECK_HEAD(head, field); \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
+ TAILQ_FIRST((head))->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ TAILQ_FIRST((head)) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
+ QMD_TRACE_HEAD(head); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ QMD_TAILQ_CHECK_TAIL(head, field); \
+ TAILQ_NEXT((elm), field) = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_HEAD(head); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
+ QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
+ QMD_TAILQ_CHECK_NEXT(elm, field); \
+ QMD_TAILQ_CHECK_PREV(elm, field); \
+ if ((TAILQ_NEXT((elm), field)) != NULL) \
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else { \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ QMD_TRACE_HEAD(head); \
+ } \
+ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
+ TRASHIT(*oldnext); \
+ TRASHIT(*oldprev); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#define TAILQ_SWAP(head1, head2, type, field) do { \
+ struct type *swap_first = (head1)->tqh_first; \
+ struct type **swap_last = (head1)->tqh_last; \
+ (head1)->tqh_first = (head2)->tqh_first; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ (head2)->tqh_first = swap_first; \
+ (head2)->tqh_last = swap_last; \
+ if ((swap_first = (head1)->tqh_first) != NULL) \
+ swap_first->field.tqe_prev = &(head1)->tqh_first; \
+ else \
+ (head1)->tqh_last = &(head1)->tqh_first; \
+ if ((swap_first = (head2)->tqh_first) != NULL) \
+ swap_first->field.tqe_prev = &(head2)->tqh_first; \
+ else \
+ (head2)->tqh_last = &(head2)->tqh_first; \
+} while (0)
+
+#endif /* !_SYS_QUEUE_H_ */
--- /dev/null
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ *
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ * Copyright (c) 2005, Keir A Fraser
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _MM_H_
+#define _MM_H_
+
+#if defined(__i386__)
+#include <xen/arch-x86_32.h>
+#elif defined(__x86_64__)
+#include <xen/arch-x86_64.h>
+#elif defined(__arm__) || defined(__aarch64__)
+#include <xen/arch-arm.h>
+#else
+#error "Unsupported architecture"
+#endif
+#include <xen/xen.h>
+
+#include <mini-os/arch_limits.h>
+#include <mini-os/arch_mm.h>
+
+#define STACK_SIZE_PAGE_ORDER __STACK_SIZE_PAGE_ORDER
+#define STACK_SIZE __STACK_SIZE
+
+
+void init_mm(void);
+unsigned long alloc_pages(int order);
+#define alloc_page() alloc_pages(0)
+void free_pages(void *pointer, int order);
+#define free_page(p) free_pages(p, 0)
+
+static __inline__ int get_order(unsigned long size)
+{
+ int order;
+ size = (size-1) >> PAGE_SHIFT;
+ for ( order = 0; size; order++ )
+ size >>= 1;
+ return order;
+}
+
+void arch_init_demand_mapping_area(unsigned long max_pfn);
+void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p);
+void arch_init_p2m(unsigned long max_pfn_p);
+
+unsigned long allocate_ondemand(unsigned long n, unsigned long alignment);
+/* map f[i*stride]+i*increment for i in 0..n-1, aligned on alignment pages */
+void *map_frames_ex(const unsigned long *f, unsigned long n, unsigned long stride,
+ unsigned long increment, unsigned long alignment, domid_t id,
+ int *err, unsigned long prot);
+void do_map_frames(unsigned long addr,
+ const unsigned long *f, unsigned long n, unsigned long stride,
+ unsigned long increment, domid_t id, int *err, unsigned long prot);
+int unmap_frames(unsigned long va, unsigned long num_frames);
+unsigned long alloc_contig_pages(int order, unsigned int addr_bits);
+#ifdef HAVE_LIBC
+extern unsigned long heap, brk, heap_mapped, heap_end;
+#endif
+
+int free_physical_pages(xen_pfn_t *mfns, int n);
+void fini_mm(void);
+
+#endif /* _MM_H_ */
--- /dev/null
+#include <mini-os/wait.h>
+#ifdef HAVE_LWIP
+#include <lwip/netif.h>
+#endif
+struct netfront_dev;
+struct netfront_dev *init_netfront(char *nodename, void (*netif_rx)(unsigned char *data, int len), unsigned char rawmac[6], char **ip);
+void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len);
+void shutdown_netfront(struct netfront_dev *dev);
+#ifdef HAVE_LIBC
+int netfront_tap_open(char *nodename);
+ssize_t netfront_receive(struct netfront_dev *dev, unsigned char *data, size_t len);
+#endif
+
+extern struct wait_queue_head netfront_queue;
+
+#ifdef HAVE_LWIP
+/* Call this to bring up the netfront interface and the lwIP stack.
+ * N.B. _must_ be called from a thread; it's not safe to call this from
+ * app_main(). */
+void start_networking(void);
+void stop_networking(void);
+
+void networking_set_addr(struct ip_addr *ipaddr, struct ip_addr *netmask, struct ip_addr *gw);
+#endif
--- /dev/null
+#include <mini-os/types.h>
+#include <xen/io/pciif.h>
+struct pcifront_dev;
+void pcifront_watches(void *opaque);
+struct pcifront_dev *init_pcifront(char *nodename);
+void pcifront_op(struct pcifront_dev *dev, struct xen_pci_op *op);
+void pcifront_scan(struct pcifront_dev *dev, void (*fun)(unsigned int domain, unsigned int bus, unsigned slot, unsigned int fun));
+int pcifront_conf_read(struct pcifront_dev *dev,
+ unsigned int dom,
+ unsigned int bus, unsigned int slot, unsigned int fun,
+ unsigned int off, unsigned int size, unsigned int *val);
+int pcifront_conf_write(struct pcifront_dev *dev,
+ unsigned int dom,
+ unsigned int bus, unsigned int slot, unsigned int fun,
+ unsigned int off, unsigned int size, unsigned int val);
+int pcifront_enable_msi(struct pcifront_dev *dev,
+ unsigned int dom,
+ unsigned int bus, unsigned int slot, unsigned int fun);
+int pcifront_disable_msi(struct pcifront_dev *dev,
+ unsigned int dom,
+ unsigned int bus, unsigned int slot, unsigned int fun);
+int pcifront_enable_msix(struct pcifront_dev *dev,
+ unsigned int dom,
+ unsigned int bus, unsigned int slot, unsigned int fun,
+ struct xen_msix_entry *entries, int n);
+int pcifront_disable_msix(struct pcifront_dev *dev,
+ unsigned int dom,
+ unsigned int bus, unsigned int slot, unsigned int fun);
+void shutdown_pcifront(struct pcifront_dev *dev);
--- /dev/null
+#ifndef _POSIX_ARPA_INET_H_
+#define _POSIX_ARPA_INET_H_
+
+#include <lwip/inet.h>
+
+#endif /* _POSIX_ARPA_INET_H_ */
+
--- /dev/null
+#ifndef _POSIX_DIRENT_H
+#define _POSIX_DIRENT_H
+
+#include <stdint.h>
+
+struct dirent {
+ char *d_name;
+};
+
+typedef struct {
+ struct dirent dirent;
+ char *name;
+ int32_t offset;
+ char **entries;
+ int32_t curentry;
+ int32_t nbentries;
+ int has_more;
+} DIR;
+
+DIR *opendir(const char *name);
+struct dirent *readdir(DIR *dir);
+int closedir(DIR *dir);
+
+#endif /* _POSIX_DIRENT_H */
--- /dev/null
+#ifndef _POSIX_ERR_H
+#define _POSIX_ERR_H
+
+#include <stdarg.h>
+
+void err(int eval, const char *fmt, ...);
+void errx(int eval, const char *fmt, ...);
+void warn(const char *fmt, ...);
+void warnx(const char *fmt, ...);
+void verr(int eval, const char *fmt, va_list args);
+void verrx(int eval, const char *fmt, va_list args);
+void vwarn(const char *fmt, va_list args);
+void vwarnx(const char *fmt, va_list args);
+
+#endif /* _POSIX_ERR_H */
--- /dev/null
+#ifndef _POSIX_FCNTL_H
+#define _POSIX_FCNTL_H
+
+#include_next <fcntl.h>
+
+#define F_ULOCK 0
+#define F_LOCK 1
+#define F_TLOCK 2
+#define F_TEST 3
+
+#endif /* _POSIX_FCNTL_H */
--- /dev/null
+#ifndef _POSIX_LIMITS_H
+#define _POSIX_LIMITS_H
+
+#include <mini-os/arch_limits.h>
+
+#define CHAR_BIT 8
+
+#define SCHAR_MAX 0x7f
+#define SCHAR_MIN (-SCHAR_MAX-1)
+#define UCHAR_MAX 0xff
+
+#ifdef __CHAR_UNSIGNED__
+# define CHAR_MIN 0
+# define CHAR_MAX UCHAR_MAX
+#else
+# define CHAR_MIN SCHAR_MIN
+# define CHAR_MAX SCHAR_MAX
+#endif
+
+#define INT_MAX 0x7fffffff
+#define INT_MIN (-INT_MAX-1)
+#define UINT_MAX 0xffffffff
+
+#define SHRT_MIN (-0x8000)
+#define SHRT_MAX 0x7fff
+#define USHRT_MAX 0xffff
+
+#if defined(__x86_64__)
+# define LONG_MAX 0x7fffffffffffffffL
+# define ULONG_MAX 0xffffffffffffffffUL
+#else
+# define LONG_MAX 0x7fffffffL
+# define ULONG_MAX 0xffffffffUL
+#endif
+#define LONG_MIN (-LONG_MAX-1L)
+
+#define LLONG_MAX 0x7fffffffffffffffLL
+#define LLONG_MIN (-LLONG_MAX-1LL)
+#define ULLONG_MAX 0xffffffffffffffffULL
+
+#define LONG_LONG_MIN LLONG_MIN
+#define LONG_LONG_MAX LLONG_MAX
+#define ULONG_LONG_MAX ULLONG_MAX
+
+#define PATH_MAX __PAGE_SIZE
+#define PAGE_SIZE __PAGE_SIZE
+
+#endif /* _POSIX_LIMITS_H */
--- /dev/null
+/*
+ * This code is mostly taken from NetBSD net/if.h
+ * Changes: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+ *
+ ******************************************************************************
+ *
+ * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by William Studenmund and Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _NET_IF_H_
+#define _NET_IF_H_
+
+/*
+ * Length of interface external name, including terminating '\0'.
+ * Note: this is the same size as a generic device's external name.
+ */
+#define IF_NAMESIZE 16
+
+struct if_nameindex {
+ unsigned int if_index; /* 1, 2, ... */
+ char *if_name; /* null terminated name: "le0", ... */
+};
+
+unsigned int if_nametoindex(const char *);
+char * if_indextoname(unsigned int, char *);
+struct if_nameindex * if_nameindex(void);
+void if_freenameindex(struct if_nameindex *);
+
+#endif /* !_NET_IF_H_ */
+
--- /dev/null
+#ifndef _POSIX_NETDB_H_
+#define _POSIX_NETDB_H_
+
+struct hostent {
+ char *h_addr;
+};
+#define gethostbyname(buf) NULL
+
+#endif /* _POSIX_NETDB_H_ */
--- /dev/null
+#ifndef _POSIX_SYS_IN_H_
+#define _POSIX_SYS_IN_H_
+
+#include <fcntl.h>
+#include <lwip/sockets.h>
+
+#endif /* _POSIX_SYS_IN_H_ */
--- /dev/null
+#ifndef _POSIX_SYS_TCP_H_
+#define _POSIX_SYS_TCP_H_
+
+#include <lwip/tcp.h>
+
+#endif /* _POSIX_SYS_TCP_H_ */
--- /dev/null
+#include <sys/poll.h>
--- /dev/null
+#ifndef _POSIX_PTHREAD_H
+#define _POSIX_PTHREAD_H
+
+#include <stdlib.h>
+
+/* Let's be single-threaded for now. */
+
+typedef struct {
+ void *ptr;
+} *pthread_key_t;
+static inline int pthread_key_create(pthread_key_t *key, void (*destr_function)(void*))
+{
+ *key = malloc(sizeof(**key));
+ (*key)->ptr = NULL;
+ return 0;
+}
+static inline int pthread_setspecific(pthread_key_t key, const void *pointer)
+{
+ key->ptr = (void*) pointer;
+ return 0;
+}
+static inline void *pthread_getspecific(pthread_key_t key)
+{
+ return key->ptr;
+}
+static inline int pthread_key_delete(pthread_key_t key)
+{
+ free(key);
+ return 0;
+}
+
+
+
+typedef struct {} pthread_mutexattr_t;
+static inline int pthread_mutexattr_init(pthread_mutexattr_t *mattr) { return 0; }
+#define PTHREAD_MUTEX_NORMAL 0
+#define PTHREAD_MUTEX_RECURSIVE 1
+static inline int pthread_mutexattr_settype(pthread_mutexattr_t *mattr, int kind) { return 0; }
+static inline int pthread_mutexattr_destroy(pthread_mutexattr_t *mattr) { return 0; }
+typedef struct {} pthread_mutex_t;
+#define PTHREAD_MUTEX_INITIALIZER {}
+static inline int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *mattr) { return 0; }
+static inline int pthread_mutex_lock(pthread_mutex_t *mutex) { return 0; }
+static inline int pthread_mutex_unlock(pthread_mutex_t *mutex) { return 0; }
+
+
+
+typedef struct {
+ int done;
+} pthread_once_t;
+#define PTHREAD_ONCE_INIT { 0 }
+
+static inline int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
+{
+ if (!once_control->done) {
+ once_control->done = 1;
+ init_routine();
+ }
+ return 0;
+}
+
+#define __thread
+
+#endif /* _POSIX_PTHREAD_H */
--- /dev/null
+#ifndef _POSIX_SIGNAL_H
+#define _POSIX_SIGNAL_H
+
+#include_next <signal.h>
+
+int sigaction(int signum, const struct sigaction * __restrict,
+ struct sigaction * __restrict);
+
+#endif
+
--- /dev/null
+#ifndef _POSIX_STDLIB_H
+#define _POSIX_STDLIB_H
+
+#include_next <stdlib.h>
+
+#define realpath(p,r) strcpy(r,p)
+
+#endif /* _POSIX_STDLIB_H */
--- /dev/null
+#ifndef _POSIX_STRINGS_H
+#define _POSIX_STRINGS_H
+
+#include <string.h>
+
+#define bzero(ptr, size) (memset((ptr), '\0', (size)), (void) 0)
+
+int ffs (int i);
+int ffsl (long int li);
+int ffsll (long long int lli);
+
+#endif /* _POSIX_STRINGS_H */
--- /dev/null
+#ifndef _POSIX_SYS_IOCTL_H
+#define _POSIX_SYS_IOCTL_H
+
+int ioctl(int fd, int request, ...);
+
+#define _IOC_NONE 0
+#define _IOC_WRITE 1
+#define _IOC_READ 2
+
+#define _IOC(rw, class, n, size) \
+ (((rw ) << 30) | \
+ ((class) << 22) | \
+ ((n ) << 14) | \
+ ((size ) << 0))
+
+#endif /* _POSIX_SYS_IOCTL_H */
--- /dev/null
+#ifndef _POSIX_SYS_MMAN_H
+#define _POSIX_SYS_MMAN_H
+
+#define PROT_READ 0x1
+#define PROT_WRITE 0x2
+#define PROT_EXEC 0x4
+
+#define MAP_SHARED 0x01
+#define MAP_PRIVATE 0x02
+#define MAP_ANON 0x20
+
+/* Pages are always resident anyway */
+#define MAP_LOCKED 0x0
+
+#define MAP_FAILED ((void*)0)
+
+void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) asm("mmap64");
+int munmap(void *start, size_t length);
+static inline mlock(const void *addr, size_t len) { return 0; }
+static inline munlock(const void *addr, size_t len) { return 0; }
+
+#endif /* _POSIX_SYS_MMAN_H */
--- /dev/null
+/*
+ * This code is mostly taken from FreeBSD sys/sys/poll.h
+ * Changes: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+ *
+ ****************************************************************************
+ * Copyright (c) 1997 Peter Wemm <peter@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _POSIX_SYS_POLL_H_
+#define _POSIX_SYS_POLL_H_
+
+/*
+ * This file is intended to be compatible with the traditional poll.h.
+ */
+
+typedef unsigned int nfds_t;
+
+/*
+ * This structure is passed as an array to poll(2).
+ */
+struct pollfd {
+ int fd; /* which file descriptor to poll */
+ short events; /* events we are interested in */
+ short revents; /* events found on return */
+};
+
+/*
+ * Requestable events. If poll(2) finds any of these set, they are
+ * copied to revents on return.
+ * XXX Note that FreeBSD doesn't make much distinction between POLLPRI
+ * and POLLRDBAND since none of the file types have distinct priority
+ * bands - and only some have an urgent "mode".
+ * XXX Note POLLIN isn't really supported in true SVSV terms. Under SYSV
+ * POLLIN includes all of normal, band and urgent data. Most poll handlers
+ * on FreeBSD only treat it as "normal" data.
+ */
+#define POLLIN 0x0001 /* any readable data available */
+#define POLLPRI 0x0002 /* OOB/Urgent readable data */
+#define POLLOUT 0x0004 /* file descriptor is writeable */
+#define POLLRDNORM 0x0040 /* non-OOB/URG data available */
+#define POLLWRNORM POLLOUT /* no write type differentiation */
+#define POLLRDBAND 0x0080 /* OOB/Urgent readable data */
+#define POLLWRBAND 0x0100 /* OOB/Urgent data can be written */
+
+/*
+ * These events are set if they occur regardless of whether they were
+ * requested.
+ */
+#define POLLERR 0x0008 /* some poll error occurred */
+#define POLLHUP 0x0010 /* file descriptor was "hung up" */
+#define POLLNVAL 0x0020 /* requested events "invalid" */
+
+int poll(struct pollfd _pfd[], nfds_t _nfds, int _timeout);
+
+#endif /* _POSIX_SYS_POLL_H_ */
--- /dev/null
+#ifndef _POSIX_SELECT_H
+#define _POSIX_SELECT_H
+
+#include <sys/time.h>
+int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
+
+#endif /* _POSIX_SELECT_H */
--- /dev/null
+#ifndef _POSIX_SYS_SOCKET_H_
+#define _POSIX_SYS_SOCKET_H_
+
+#include <fcntl.h>
+#include <lwip/sockets.h>
+
+int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+int bind(int s, struct sockaddr *name, socklen_t namelen);
+int shutdown(int s, int how);
+int getpeername (int s, struct sockaddr *name, socklen_t *namelen);
+int getsockname (int s, struct sockaddr *name, socklen_t *namelen);
+int getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen);
+int setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen);
+int close(int s);
+int connect(int s, struct sockaddr *name, socklen_t namelen);
+int listen(int s, int backlog);
+int recv(int s, void *mem, int len, unsigned int flags);
+//int read(int s, void *mem, int len);
+int recvfrom(int s, void *mem, int len, unsigned int flags,
+ struct sockaddr *from, socklen_t *fromlen);
+int send(int s, void *dataptr, int size, unsigned int flags);
+int sendto(int s, void *dataptr, int size, unsigned int flags,
+ struct sockaddr *to, socklen_t tolen);
+int socket(int domain, int type, int protocol);
+//int write(int s, void *dataptr, int size);
+int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
+ struct timeval *timeout);
+//int ioctl(int s, long cmd, void *argp);
+int getsockname(int s, struct sockaddr *name, socklen_t *namelen);
+
+#endif /* _POSIX_SYS_SOCKET_H_ */
--- /dev/null
+#ifndef _POSIX_SYS_STAT_H
+#define _POSIX_SYS_STAT_H
+
+#include_next <sys/stat.h>
+int fstat(int fd, struct stat *buf) asm("fstat64");
+
+#endif /* _POSIX_SYS_STAT_H */
--- /dev/null
+#ifndef _POSIX_SYSLOG_H
+#define _POSIX_SYSLOG_H
+
+#include <stdarg.h>
+
+#define LOG_PID 0
+#define LOG_CONS 0
+#define LOG_NDELAY 0
+#define LOG_ODELAY 0
+#define LOG_NOWAIT 0
+
+#define LOG_KERN 0
+#define LOG_USER 0
+#define LOG_MAIL 0
+#define LOG_NEWS 0
+#define LOG_UUCP 0
+#define LOG_DAEMON 0
+#define LOG_AUTH 0
+#define LOG_CRON 0
+#define LOG_LPR 0
+
+/* TODO: support */
+#define LOG_EMERG 0
+#define LOG_ALERT 1
+#define LOG_CRIT 2
+#define LOG_ERR 3
+#define LOG_WARNING 4
+#define LOG_NOTICE 5
+#define LOG_INFO 6
+#define LOG_DEBUG 7
+
+void openlog(const char *ident, int option, int facility);
+void syslog(int priority, const char *format, ...);
+void closelog(void);
+void vsyslog(int priority, const char *format, va_list ap);
+
+#endif /* _POSIX_SYSLOG_H */
--- /dev/null
+#ifndef _POSIX_TERMIOS_H
+#define _POSIX_TERMIOS_H
+
+#define NCC 32
+
+struct termios {
+ unsigned long c_iflag;
+ unsigned long c_oflag;
+ unsigned long c_lflag;
+ unsigned long c_cflag;
+ unsigned char c_cc[NCC];
+};
+
+/* modem lines */
+#define TIOCM_DTR 0x002
+#define TIOCM_RTS 0x004
+#define TIOCM_CTS 0x020
+#define TIOCM_CAR 0x040
+#define TIOCM_RI 0x080
+#define TIOCM_DSR 0x100
+
+/* c_iflag */
+#define IGNBRK 0x00000001
+#define BRKINT 0x00000002
+#define IGNPAR 0x00000004
+#define PARMRK 0x00000008
+#define INPCK 0x00000010
+#define ISTRIP 0x00000020
+#define INLCR 0x00000040
+#define IGNCR 0x00000080
+#define ICRNL 0x00000100
+#define IUCLC 0x00000200
+#define IXON 0x00000400
+#define IXANY 0x00000800
+#define IXOFF 0x00001000
+#define IMAXBEL 0x00002000
+#define IUTF8 0x00004000
+
+/* c_oflag */
+#define OPOST 0x00000001
+#define OLCUC 0x00000002
+#define ONLCR 0x00000004
+#define OCRNL 0x00000008
+#define ONOCR 0x00000010
+#define ONLRET 0x00000020
+#define OFILL 0x00000040
+#define OFDEL 0x00000080
+
+/* c_lflag */
+#define ISIG 0x00000001
+#define ICANON 0x00000002
+#define XCASE 0x00000004
+#define ECHO 0x00000008
+#define ECHOE 0x00000010
+#define ECHOK 0x00000020
+#define ECHONL 0x00000040
+#define NOFLSH 0x00000080
+#define TOSTOP 0x00000100
+#define ECHOCTL 0x00000200
+#define ECHOPRT 0x00000400
+#define ECHOKE 0x00000800
+#define FLUSHO 0x00002000
+#define PENDIN 0x00004000
+#define IEXTEN 0x00008000
+
+/* c_cflag */
+#define CSIZE 0x00000030
+#define CS8 0x00000030
+#define CSTOPB 0x00000040
+#define CREAD 0x00000080
+#define PARENB 0x00000100
+#define PARODD 0x00000200
+#define HUPCL 0x00000400
+#define CLOCAL 0x00000800
+
+/* c_cc */
+#define VTIME 5
+#define VMIN 6
+
+#define TCSANOW 0
+#define TCSADRAIN 1
+#define TCSAFLUSH 2
+
+int tcsetattr(int fildes, int action, const struct termios *tios);
+int tcgetattr(int fildes, struct termios *tios);
+
+#endif /* _POSIX_TERMIOS_H */
--- /dev/null
+#ifndef _POSIX_TIME_H
+#define _POSIX_TIME_H
+
+#include <sys/time.h>
+#define CLOCK_MONOTONIC 2
+#include_next <time.h>
+
+int nanosleep(const struct timespec *req, struct timespec *rem);
+int clock_gettime(clockid_t clock_id, struct timespec *tp);
+
+#endif /* _POSIX_TIME_H */
--- /dev/null
+#ifndef _POSIX_UNISTD_H
+#define _POSIX_UNISTD_H
+
+#include_next <unistd.h>
+
+uid_t getuid(void);
+uid_t geteuid(void);
+gid_t getgid(void);
+gid_t getegid(void);
+int gethostname(char *name, size_t namelen);
+size_t getpagesize(void);
+int ftruncate(int fd, off_t length);
+int lockf(int fd, int cmd, off_t len);
+int nice(int inc);
+
+#endif /* _POSIX_UNISTD_H */
--- /dev/null
+#ifndef __SCHED_H__
+#define __SCHED_H__
+
+#include <mini-os/list.h>
+#include <mini-os/time.h>
+#include <mini-os/arch_sched.h>
+#ifdef HAVE_LIBC
+#include <sys/reent.h>
+#endif
+
+struct thread
+{
+ char *name;
+ char *stack;
+ /* keep in that order */
+ unsigned long sp; /* Stack pointer */
+ unsigned long ip; /* Instruction pointer */
+ MINIOS_TAILQ_ENTRY(struct thread) thread_list;
+ uint32_t flags;
+ s_time_t wakeup_time;
+#ifdef HAVE_LIBC
+ struct _reent reent;
+#endif
+};
+
+extern struct thread *idle_thread;
+void idle_thread_fn(void *unused);
+
+#define RUNNABLE_FLAG 0x00000001
+
+#define is_runnable(_thread) (_thread->flags & RUNNABLE_FLAG)
+#define set_runnable(_thread) (_thread->flags |= RUNNABLE_FLAG)
+#define clear_runnable(_thread) (_thread->flags &= ~RUNNABLE_FLAG)
+
+#define switch_threads(prev, next) arch_switch_threads(prev, next)
+
+ /* Architecture specific setup of thread creation. */
+struct thread* arch_create_thread(char *name, void (*function)(void *),
+ void *data);
+
+void init_sched(void);
+void run_idle_thread(void);
+struct thread* create_thread(char *name, void (*function)(void *), void *data);
+void exit_thread(void) __attribute__((noreturn));
+void schedule(void);
+
+#ifdef __INSIDE_MINIOS__
+#define current get_current()
+#endif
+
+void wake(struct thread *thread);
+void block(struct thread *thread);
+void msleep(uint32_t millisecs);
+
+#endif /* __SCHED_H__ */
--- /dev/null
+#ifndef _SEMAPHORE_H_
+#define _SEMAPHORE_H_
+
+#include <mini-os/wait.h>
+#include <mini-os/spinlock.h>
+
+/*
+ * Implementation of semaphore in Mini-os is simple, because
+ * there are no preemptive threads, the atomicity is guaranteed.
+ */
+
+struct semaphore
+{
+ int count;
+ struct wait_queue_head wait;
+};
+
+/*
+ * the semaphore definition
+ */
+struct rw_semaphore {
+ signed long count;
+ spinlock_t wait_lock;
+ int debug;
+};
+
+#define __SEMAPHORE_INITIALIZER(name, n) \
+{ \
+ .count = n, \
+ .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+}
+
+#define __MUTEX_INITIALIZER(name) \
+ __SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+static inline void init_SEMAPHORE(struct semaphore *sem, int count)
+{
+ sem->count = count;
+ init_waitqueue_head(&sem->wait);
+}
+
+#define init_MUTEX(sem) init_SEMAPHORE(sem, 1)
+
+static inline int trydown(struct semaphore *sem)
+{
+ unsigned long flags;
+ int ret = 0;
+ local_irq_save(flags);
+ if (sem->count > 0) {
+ ret = 1;
+ sem->count--;
+ }
+ local_irq_restore(flags);
+ return ret;
+}
+
+static void inline down(struct semaphore *sem)
+{
+ unsigned long flags;
+ while (1) {
+ wait_event(sem->wait, sem->count > 0);
+ local_irq_save(flags);
+ if (sem->count > 0)
+ break;
+ local_irq_restore(flags);
+ }
+ sem->count--;
+ local_irq_restore(flags);
+}
+
+static void inline up(struct semaphore *sem)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+ sem->count++;
+ wake_up(&sem->wait);
+ local_irq_restore(flags);
+}
+
+/* FIXME! Thre read/write semaphores are unimplemented! */
+static inline void init_rwsem(struct rw_semaphore *sem)
+{
+ sem->count = 1;
+}
+
+static inline void down_read(struct rw_semaphore *sem)
+{
+}
+
+
+static inline void up_read(struct rw_semaphore *sem)
+{
+}
+
+static inline void up_write(struct rw_semaphore *sem)
+{
+}
+
+static inline void down_write(struct rw_semaphore *sem)
+{
+}
+
+#endif /* _SEMAPHORE_H */
--- /dev/null
+#ifndef __ASM_SPINLOCK_H
+#define __ASM_SPINLOCK_H
+
+#include <mini-os/lib.h>
+
+/*
+ * Your basic SMP spinlocks, allowing only a single CPU anywhere
+ */
+
+typedef struct {
+ volatile unsigned int slock;
+} spinlock_t;
+
+
+#include <mini-os/arch_spinlock.h>
+
+
+#define SPINLOCK_MAGIC 0xdead4ead
+
+#define SPIN_LOCK_UNLOCKED ARCH_SPIN_LOCK_UNLOCKED
+
+#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
+
+/*
+ * Simple spin lock operations. There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions. They have a cost.
+ */
+
+#define spin_is_locked(x) arch_spin_is_locked(x)
+
+#define spin_unlock_wait(x) arch_spin_unlock_wait(x)
+
+
+#define _spin_trylock(lock) ({_raw_spin_trylock(lock) ? \
+ 1 : ({ 0;});})
+
+#define _spin_lock(lock) \
+do { \
+ _raw_spin_lock(lock); \
+} while(0)
+
+#define _spin_unlock(lock) \
+do { \
+ _raw_spin_unlock(lock); \
+} while (0)
+
+
+#define spin_lock(lock) _spin_lock(lock)
+#define spin_unlock(lock) _spin_unlock(lock)
+
+#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
+
+#endif
--- /dev/null
+#ifndef _MINIOS_SYS_LOCK_H_
+#define _MINIOS_SYS_LOCK_H_
+
+#ifdef HAVE_LIBC
+
+/* Due to inclusion loop, we can not include sched.h, so have to hide things */
+
+#include <mini-os/waittypes.h>
+
+
+typedef struct {
+ int busy;
+ struct wait_queue_head wait;
+} _LOCK_T;
+
+#define __LOCK_INIT(class,lock) \
+ class _LOCK_T lock = { .wait = __WAIT_QUEUE_HEAD_INITIALIZER(lock.wait) }
+int ___lock_init(_LOCK_T *lock);
+int ___lock_acquire(_LOCK_T *lock);
+int ___lock_try_acquire(_LOCK_T *lock);
+int ___lock_release(_LOCK_T *lock);
+int ___lock_close(_LOCK_T *lock);
+#define __lock_init(__lock) ___lock_init(&__lock)
+#define __lock_acquire(__lock) ___lock_acquire(&__lock)
+#define __lock_release(__lock) ___lock_release(&__lock)
+#define __lock_try_acquire(__lock) ___lock_try_acquire(&__lock)
+#define __lock_close(__lock) 0
+
+
+typedef struct {
+ struct thread *owner;
+ int count;
+ struct wait_queue_head wait;
+} _LOCK_RECURSIVE_T;
+
+#define __LOCK_INIT_RECURSIVE(class, lock) \
+ class _LOCK_RECURSIVE_T lock = { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((lock).wait) }
+
+int ___lock_init_recursive(_LOCK_RECURSIVE_T *lock);
+int ___lock_acquire_recursive(_LOCK_RECURSIVE_T *lock);
+int ___lock_try_acquire_recursive(_LOCK_RECURSIVE_T *lock);
+int ___lock_release_recursive(_LOCK_RECURSIVE_T *lock);
+int ___lock_close_recursive(_LOCK_RECURSIVE_T *lock);
+#define __lock_init_recursive(__lock) ___lock_init_recursive(&__lock)
+#define __lock_acquire_recursive(__lock) ___lock_acquire_recursive(&__lock)
+#define __lock_release_recursive(__lock) ___lock_release_recursive(&__lock)
+#define __lock_try_acquire_recursive(__lock) ___lock_try_acquire_recursive(&__lock)
+#define __lock_close_recursive(__lock) 0
+
+#endif
+
+#endif /* _MINIOS_SYS_LOCK_H_ */
--- /dev/null
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: time.h
+ * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
+ * Changes: Grzegorz Milos (gm281@cam.ac.uk)
+ * Robert Kaiser (kaiser@informatik.fh-wiesbaden.de)
+ *
+ * Date: Jul 2003, changes: Jun 2005, Sep 2006
+ *
+ * Environment: Xen Minimal OS
+ * Description: Time and timer functions
+ *
+ ****************************************************************************
+ */
+
+#ifndef _MINIOS_SYS_TIME_H_
+#define _MINIOS_SYS_TIME_H_
+
+#ifdef HAVE_LIBC
+#include_next <sys/time.h>
+
+#else
+struct timespec {
+ time_t tv_sec;
+ long tv_nsec;
+};
+
+struct timezone {
+};
+
+struct timeval {
+ time_t tv_sec; /* seconds */
+ suseconds_t tv_usec; /* microseconds */
+};
+
+int gettimeofday(struct timeval *tv, void *tz);
+
+#endif
+#ifdef HAVE_LIBC
+#include <sys/select.h>
+#endif
+
+#endif /* _MINIOS_SYS_TIME_H_ */
--- /dev/null
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: time.h
+ * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
+ * Changes: Grzegorz Milos (gm281@cam.ac.uk)
+ * Robert Kaiser (kaiser@informatik.fh-wiesbaden.de)
+ *
+ * Date: Jul 2003, changes: Jun 2005, Sep 2006
+ *
+ * Environment: Xen Minimal OS
+ * Description: Time and timer functions
+ *
+ ****************************************************************************
+ */
+
+#ifndef _MINIOS_TIME_H_
+#define _MINIOS_TIME_H_
+#include <mini-os/types.h>
+
+/*
+ * System Time
+ * 64 bit value containing the nanoseconds elapsed since boot time.
+ * This value is adjusted by frequency drift.
+ * NOW() returns the current time.
+ * The other macros are for convenience to approximate short intervals
+ * of real time into system time
+ */
+typedef int64_t s_time_t;
+#define NOW() ((s_time_t)monotonic_clock())
+#define SECONDS(_s) (((s_time_t)(_s)) * 1000000000UL )
+#define TENTHS(_ts) (((s_time_t)(_ts)) * 100000000UL )
+#define HUNDREDTHS(_hs) (((s_time_t)(_hs)) * 10000000UL )
+#define MILLISECS(_ms) (((s_time_t)(_ms)) * 1000000UL )
+#define MICROSECS(_us) (((s_time_t)(_us)) * 1000UL )
+#define Time_Max ((s_time_t) 0x7fffffffffffffffLL)
+#define FOREVER Time_Max
+#define NSEC_TO_USEC(_nsec) ((_nsec) / 1000UL)
+#define NSEC_TO_MSEC(_nsec) ((_nsec) / 1000000ULL)
+#define NSEC_TO_SEC(_nsec) ((_nsec) / 1000000000ULL)
+
+/* wall clock time */
+typedef long time_t;
+typedef long suseconds_t;
+
+#include <sys/time.h>
+
+#ifdef HAVE_LIBC
+#include_next <time.h>
+#endif
+
+/* prototypes */
+void init_time(void);
+void fini_time(void);
+s_time_t get_s_time(void);
+s_time_t get_v_time(void);
+uint64_t monotonic_clock(void);
+void block_domain(s_time_t until);
+
+#endif /* _MINIOS_TIME_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense. All rights reserved.
+ *
+ * This code has been derived from drivers/char/tpm.c
+ * from the linux kernel
+ *
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * This code has also been derived from drivers/char/tpm/tpm_tis.c
+ * from the linux kernel
+ *
+ * Copyright (C) 2005, 2006 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, version 2
+ * of the License
+ */
+#ifndef TPM_TIS_H
+#define TPM_TIS_H
+
+#include <mini-os/types.h>
+#include <mini-os/byteorder.h>
+
+#define TPM_TIS_EN_LOCL0 1
+#define TPM_TIS_EN_LOCL1 (1 << 1)
+#define TPM_TIS_EN_LOCL2 (1 << 2)
+#define TPM_TIS_EN_LOCL3 (1 << 3)
+#define TPM_TIS_EN_LOCL4 (1 << 4)
+#define TPM_TIS_EN_LOCLALL (TPM_TIS_EN_LOCL0 | TPM_TIS_EN_LOCL1 | TPM_TIS_EN_LOCL2 | TPM_TIS_EN_LOCL3 | TPM_TIS_EN_LOCL4)
+#define TPM_TIS_LOCL_INT_TO_FLAG(x) (1 << x)
+#define TPM_BASEADDR 0xFED40000
+#define TPM_PROBE_IRQ 0xFFFF
+
+struct tpm_chip;
+
+struct tpm_chip* init_tpm_tis(unsigned long baseaddr, int localities, unsigned int irq);
+struct tpm_chip* init_tpm2_tis(unsigned long baseaddr, int localities, unsigned int irq);
+void shutdown_tpm_tis(struct tpm_chip* tpm);
+
+int tpm_tis_request_locality(struct tpm_chip* tpm, int locality);
+int tpm_tis_cmd(struct tpm_chip* tpm, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen);
+
+#ifdef HAVE_LIBC
+#include <sys/stat.h>
+#include <fcntl.h>
+/* POSIX IO functions:
+ * use tpm_tis_open() to get a file descriptor to the tpm device
+ * use write() on the fd to send a command to the backend. You must
+ * include the entire command in a single call to write().
+ * use read() on the fd to read the response. You can use
+ * fstat() to get the size of the response and lseek() to seek on it.
+ */
+int tpm_tis_open(struct tpm_chip* tpm);
+int tpm_tis_posix_read(int fd, uint8_t* buf, size_t count);
+int tpm_tis_posix_write(int fd, const uint8_t* buf, size_t count);
+int tpm_tis_posix_fstat(int fd, struct stat* buf);
+#endif
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense. All rights reserved.
+ *
+ * This code has been derived from drivers/xen/tpmback/tpmback.c
+ * from the xen 2.6.18 linux kernel
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * which was itself derived from drivers/xen/netback/netback.c
+ * from the xen 2.6.18 linux kernel
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * This code has also been derived from drivers/xen/tpmback/xenbus.c
+ * from the xen 2.6.18 linux kernel
+ *
+ * Copyright (C) 2005 IBM Corporation
+ * Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
+ *
+ * This code has also been derived from drivers/xen/tpmback/interface.c
+ * from the xen 2.6.18 linux kernel
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * which was itself also derived from drvivers/xen/netback/interface.c
+ * from the xen 2.6.18 linux kernel
+ *
+ * Copyright (c) 2004, Keir Fraser
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, version 2
+ * of the License
+ */
+
+#include <xen/io/tpmif.h>
+#include <xen/io/xenbus.h>
+#include <mini-os/types.h>
+#include <xen/xen.h>
+#ifndef TPMBACK_H
+#define TPMBACK_H
+
+struct tpmcmd {
+ domid_t domid; /* Domid of the frontend */
+ uint8_t locality; /* Locality requested by the frontend */
+ unsigned int handle; /* Handle of the frontend */
+ void *opaque; /* Opaque pointer taken from the tpmback instance */
+
+ uint8_t* req; /* tpm command bits, allocated by driver, DON'T FREE IT */
+ unsigned int req_len; /* Size of the command in buf - set by tpmback driver */
+ unsigned int resp_len; /* Size of the outgoing command,
+ you set this before passing the cmd object to tpmback_resp */
+ uint8_t* resp; /* Buffer for response - YOU MUST ALLOCATE IT, YOU MUST ALSO FREE IT */
+};
+typedef struct tpmcmd tpmcmd_t;
+
+/* Initialize the tpm backend driver */
+void init_tpmback(void (*open_cb)(domid_t, unsigned int), void (*close_cb)(domid_t, unsigned int));
+
+/* Shutdown tpm backend driver */
+void shutdown_tpmback(void);
+
+/* Blocks until a tpm command is sent from any front end.
+ * Returns a pointer to the tpm command to handle.
+ * Do not try to free this pointer or the req buffer
+ * This function will return NULL if the tpm backend driver
+ * is shutdown or any other error occurs */
+tpmcmd_t* tpmback_req_any(void);
+
+/* Blocks until a tpm command from the frontend at domid/handle
+ * is sent.
+ * Returns NULL if domid/handle is not connected, tpmback is
+ * shutdown or shutting down, or if there is an error
+ */
+tpmcmd_t* tpmback_req(domid_t domid, unsigned int handle);
+
+/* Send the response to the tpm command back to the frontend
+ * This function will free the tpmcmd object, but you must free the resp
+ * buffer yourself */
+void tpmback_resp(tpmcmd_t* tpmcmd);
+
+/* Waits for the first frontend to connect and then sets domid and handle appropriately.
+ * If one or more frontends are already connected, this will set domid and handle to one
+ * of them arbitrarily. The main use for this function is to wait until a single
+ * frontend connection has occured.
+ * returns 0 on success, non-zero on failure */
+int tpmback_wait_for_frontend_connect(domid_t *domid, unsigned int *handle);
+
+/* returns the number of frontends connected */
+int tpmback_num_frontends(void);
+
+/* Returns the uuid of the specified frontend, NULL on error.
+ * The return value is internally allocated, so don't free it */
+unsigned char* tpmback_get_uuid(domid_t domid, unsigned int handle);
+
+/* Get and set the opaque pointer for a tpmback instance */
+void* tpmback_get_opaque(domid_t domid, unsigned int handle);
+/* Returns zero if successful, nonzero on failure (no such frontend) */
+int tpmback_set_opaque(domid_t domid, unsigned int handle, void* opaque);
+
+/* Get the XSM context of the given domain (using the tpmback event channel) */
+int tpmback_get_peercontext(domid_t domid, unsigned int handle, void* buffer, int buflen);
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense. All rights reserved.
+ *
+ * This code has been derived from drivers/char/tpm_vtpm.c
+ * from the xen 2.6.18 linux kernel
+ *
+ * Copyright (C) 2006 IBM Corporation
+ *
+ * This code has also been derived from drivers/char/tpm_xen.c
+ * from the xen 2.6.18 linux kernel
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * which was itself derived from drivers/xen/netfront/netfront.c
+ * from the linux kernel
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+#ifndef TPMFRONT_H
+#define TPMFRONT_H
+
+#include <mini-os/types.h>
+#include <mini-os/os.h>
+#include <mini-os/events.h>
+#include <mini-os/wait.h>
+#include <xen/xen.h>
+#include <xen/io/xenbus.h>
+#include <xen/io/tpmif.h>
+
+struct tpmfront_dev {
+ grant_ref_t ring_ref;
+ evtchn_port_t evtchn;
+
+ tpmif_shared_page_t *page;
+
+ domid_t bedomid;
+ char* nodename;
+ char* bepath;
+
+ XenbusState state;
+
+ uint8_t waiting;
+ struct wait_queue_head waitq;
+
+ uint8_t* respbuf;
+ size_t resplen;
+
+#ifdef HAVE_LIBC
+ int fd;
+#endif
+
+};
+
+
+/*Initialize frontend */
+struct tpmfront_dev* init_tpmfront(const char* nodename);
+/*Shutdown frontend */
+void shutdown_tpmfront(struct tpmfront_dev* dev);
+
+/* Send a tpm command to the backend and wait for the response
+ *
+ * @dev - frontend device
+ * @req - request buffer
+ * @reqlen - length of request buffer
+ * @resp - *resp will be set to internal response buffer, don't free it! Value is undefined on error
+ * @resplen - *resplen will be set to the length of the response. Value is undefined on error
+ *
+ * returns 0 on success, non zero on failure.
+ * */
+int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen);
+
+/* Set the locality used for communicating with a vTPM */
+int tpmfront_set_locality(struct tpmfront_dev* dev, int locality);
+
+#ifdef HAVE_LIBC
+#include <sys/stat.h>
+/* POSIX IO functions:
+ * use tpmfront_open() to get a file descriptor to the tpm device
+ * use write() on the fd to send a command to the backend. You must
+ * include the entire command in a single call to write().
+ * use read() on the fd to read the response. You can use
+ * fstat() to get the size of the response and lseek() to seek on it.
+ */
+int tpmfront_open(struct tpmfront_dev* dev);
+int tpmfront_posix_read(int fd, uint8_t* buf, size_t count);
+int tpmfront_posix_write(int fd, const uint8_t* buf, size_t count);
+int tpmfront_posix_fstat(int fd, struct stat* buf);
+#endif
+
+
+#endif
--- /dev/null
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: types.h
+ * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
+ * Changes:
+ *
+ * Date: May 2003
+ *
+ * Environment: Xen Minimal OS
+ * Description: a random collection of type definitions
+ *
+ ****************************************************************************
+ * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
+ ****************************************************************************
+ */
+
+#ifndef _TYPES_H_
+#define _TYPES_H_
+#include <stddef.h>
+
+/* FreeBSD compat types */
+#ifndef HAVE_LIBC
+typedef unsigned char u_char;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+#endif
+#if defined(__i386__) || defined(__arm__)
+typedef long long quad_t;
+typedef unsigned long long u_quad_t;
+#elif defined(__x86_64__)
+typedef long quad_t;
+typedef unsigned long u_quad_t;
+#endif /* __i386__ || __x86_64__ */
+
+#ifdef HAVE_LIBC
+#include <limits.h>
+#include <stdint.h>
+#else
+#if defined(__i386__) || defined(__arm__)
+typedef unsigned int uintptr_t;
+typedef int intptr_t;
+#elif defined(__x86_64__) || defined(__aarch64__)
+typedef unsigned long uintptr_t;
+typedef long intptr_t;
+#endif /* __i386__ || __x86_64__ */
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+typedef unsigned int uint32_t;
+typedef signed int int32_t;
+#if defined(__i386__) || defined(__arm__)
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+#elif defined(__x86_64__) || defined(__aarch64__)
+typedef signed long int64_t;
+typedef unsigned long uint64_t;
+#endif
+typedef uint64_t uintmax_t;
+typedef int64_t intmax_t;
+typedef int64_t off_t;
+#endif
+
+typedef intptr_t ptrdiff_t;
+
+
+#ifndef HAVE_LIBC
+typedef long ssize_t;
+#endif
+
+#endif /* _TYPES_H_ */
--- /dev/null
+#ifndef __WAIT_H__
+#define __WAIT_H__
+
+#include <mini-os/sched.h>
+#include <mini-os/os.h>
+#include <mini-os/waittypes.h>
+
+#define DEFINE_WAIT(name) \
+struct wait_queue name = { \
+ .thread = get_current(), \
+ .waiting = 0, \
+}
+
+
+static inline void init_waitqueue_head(struct wait_queue_head *h)
+{
+ MINIOS_STAILQ_INIT(h);
+}
+
+static inline void init_waitqueue_entry(struct wait_queue *q, struct thread *thread)
+{
+ q->thread = thread;
+ q->waiting = 0;
+}
+
+static inline void add_wait_queue(struct wait_queue_head *h, struct wait_queue *q)
+{
+ if (!q->waiting) {
+ MINIOS_STAILQ_INSERT_HEAD(h, q, thread_list);
+ q->waiting = 1;
+ }
+}
+
+static inline void remove_wait_queue(struct wait_queue_head *h, struct wait_queue *q)
+{
+ if (q->waiting) {
+ MINIOS_STAILQ_REMOVE(h, q, struct wait_queue, thread_list);
+ q->waiting = 0;
+ }
+}
+
+static inline void wake_up(struct wait_queue_head *head)
+{
+ unsigned long flags;
+ struct wait_queue *curr, *tmp;
+ local_irq_save(flags);
+ MINIOS_STAILQ_FOREACH_SAFE(curr, head, thread_list, tmp)
+ wake(curr->thread);
+ local_irq_restore(flags);
+}
+
+#define add_waiter(w, wq) do { \
+ unsigned long flags; \
+ local_irq_save(flags); \
+ add_wait_queue(&wq, &w); \
+ block(get_current()); \
+ local_irq_restore(flags); \
+} while (0)
+
+#define remove_waiter(w, wq) do { \
+ unsigned long flags; \
+ local_irq_save(flags); \
+ remove_wait_queue(&wq, &w); \
+ local_irq_restore(flags); \
+} while (0)
+
+#define wait_event_deadline(wq, condition, deadline) do { \
+ unsigned long flags; \
+ DEFINE_WAIT(__wait); \
+ if(condition) \
+ break; \
+ for(;;) \
+ { \
+ /* protect the list */ \
+ local_irq_save(flags); \
+ add_wait_queue(&wq, &__wait); \
+ get_current()->wakeup_time = deadline; \
+ clear_runnable(get_current()); \
+ local_irq_restore(flags); \
+ if((condition) || (deadline && NOW() >= deadline)) \
+ break; \
+ schedule(); \
+ } \
+ local_irq_save(flags); \
+ /* need to wake up */ \
+ wake(get_current()); \
+ remove_wait_queue(&wq, &__wait); \
+ local_irq_restore(flags); \
+} while(0)
+
+#define wait_event(wq, condition) wait_event_deadline(wq, condition, 0)
+
+
+
+#endif /* __WAIT_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+#ifndef __WAITTYPE_H__
+#define __WAITTYPE_H__
+
+#include <mini-os/list.h>
+
+struct thread;
+struct wait_queue
+{
+ int waiting;
+ struct thread *thread;
+ MINIOS_STAILQ_ENTRY(struct wait_queue) thread_list;
+};
+
+/* TODO - lock required? */
+MINIOS_STAILQ_HEAD(wait_queue_head, struct wait_queue);
+
+#define DECLARE_WAIT_QUEUE_HEAD(name) \
+ struct wait_queue_head name = MINIOS_STAILQ_HEAD_INITIALIZER(name)
+
+#define __WAIT_QUEUE_HEAD_INITIALIZER(name) MINIOS_STAILQ_HEAD_INITIALIZER(name)
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+#ifndef ARCH_ENDIAN_H
+#error "Do not include arch_endian by itself, include endian.h"
+#else
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+#endif
--- /dev/null
+
+#ifndef __ARCH_LIMITS_H__
+#define __ARCH_LIMITS_H__
+
+#define __PAGE_SHIFT 12
+
+#ifdef __ASSEMBLY__
+#define __PAGE_SIZE (1 << __PAGE_SHIFT)
+#else
+#ifdef __x86_64__
+#define __PAGE_SIZE (1UL << __PAGE_SHIFT)
+#else
+#define __PAGE_SIZE (1ULL << __PAGE_SHIFT)
+#endif
+#endif
+
+#define __STACK_SIZE_PAGE_ORDER 4
+#define __STACK_SIZE (__PAGE_SIZE * (1 << __STACK_SIZE_PAGE_ORDER))
+
+#endif /* __ARCH_LIMITS_H__ */
--- /dev/null
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ *
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ * Copyright (c) 2005, Keir A Fraser
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _ARCH_MM_H_
+#define _ARCH_MM_H_
+
+#ifndef __ASSEMBLY__
+#include <xen/xen.h>
+#if defined(__i386__)
+#include <xen/arch-x86_32.h>
+#elif defined(__x86_64__)
+#include <xen/arch-x86_64.h>
+#else
+#error "Unsupported architecture"
+#endif
+#endif
+
+#define L1_FRAME 1
+#define L2_FRAME 2
+#define L3_FRAME 3
+
+#define L1_PAGETABLE_SHIFT 12
+
+#if defined(__i386__)
+
+#define L2_PAGETABLE_SHIFT 21
+#define L3_PAGETABLE_SHIFT 30
+
+#define L1_PAGETABLE_ENTRIES 512
+#define L2_PAGETABLE_ENTRIES 512
+#define L3_PAGETABLE_ENTRIES 4
+
+#define PADDR_BITS 44
+#define PADDR_MASK ((1ULL << PADDR_BITS)-1)
+
+#define L2_MASK ((1UL << L3_PAGETABLE_SHIFT) - 1)
+
+/*
+ * If starting from virtual address greater than 0xc0000000,
+ * this value will be 2 to account for final mid-level page
+ * directory which is always mapped in at this location.
+ */
+#define NOT_L1_FRAMES 3
+#define PRIpte "016llx"
+#ifndef __ASSEMBLY__
+typedef uint64_t pgentry_t;
+#endif
+
+#elif defined(__x86_64__)
+
+#define L2_PAGETABLE_SHIFT 21
+#define L3_PAGETABLE_SHIFT 30
+#define L4_PAGETABLE_SHIFT 39
+
+#define L1_PAGETABLE_ENTRIES 512
+#define L2_PAGETABLE_ENTRIES 512
+#define L3_PAGETABLE_ENTRIES 512
+#define L4_PAGETABLE_ENTRIES 512
+
+/* These are page-table limitations. Current CPUs support only 40-bit phys. */
+#define PADDR_BITS 52
+#define VADDR_BITS 48
+#define PADDR_MASK ((1UL << PADDR_BITS)-1)
+#define VADDR_MASK ((1UL << VADDR_BITS)-1)
+
+#define L2_MASK ((1UL << L3_PAGETABLE_SHIFT) - 1)
+#define L3_MASK ((1UL << L4_PAGETABLE_SHIFT) - 1)
+
+#define NOT_L1_FRAMES 3
+#define PRIpte "016lx"
+#ifndef __ASSEMBLY__
+typedef unsigned long pgentry_t;
+#endif
+
+#endif
+
+#define L1_MASK ((1UL << L2_PAGETABLE_SHIFT) - 1)
+
+/* Given a virtual address, get an entry offset into a page table. */
+#define l1_table_offset(_a) \
+ (((_a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
+#define l2_table_offset(_a) \
+ (((_a) >> L2_PAGETABLE_SHIFT) & (L2_PAGETABLE_ENTRIES - 1))
+#define l3_table_offset(_a) \
+ (((_a) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1))
+#if defined(__x86_64__)
+#define l4_table_offset(_a) \
+ (((_a) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1))
+#endif
+
+#define _PAGE_PRESENT 0x001ULL
+#define _PAGE_RW 0x002ULL
+#define _PAGE_USER 0x004ULL
+#define _PAGE_PWT 0x008ULL
+#define _PAGE_PCD 0x010ULL
+#define _PAGE_ACCESSED 0x020ULL
+#define _PAGE_DIRTY 0x040ULL
+#define _PAGE_PAT 0x080ULL
+#define _PAGE_PSE 0x080ULL
+#define _PAGE_GLOBAL 0x100ULL
+
+#if defined(__i386__)
+#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
+#define L1_PROT_RO (_PAGE_PRESENT|_PAGE_ACCESSED)
+#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY |_PAGE_USER)
+#define L3_PROT (_PAGE_PRESENT)
+#elif defined(__x86_64__)
+#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
+#define L1_PROT_RO (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_USER)
+#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
+#define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
+#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
+#endif /* __i386__ || __x86_64__ */
+
+/* flags for ioremap */
+#define IO_PROT (L1_PROT)
+#define IO_PROT_NOCACHE (L1_PROT | _PAGE_PCD)
+
+/* for P2M */
+#define INVALID_P2M_ENTRY (~0UL)
+
+#include "arch_limits.h"
+#define PAGE_SIZE __PAGE_SIZE
+#define PAGE_SHIFT __PAGE_SHIFT
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT)
+#define PFN_DOWN(x) ((x) >> L1_PAGETABLE_SHIFT)
+#define PFN_PHYS(x) ((uint64_t)(x) << L1_PAGETABLE_SHIFT)
+#define PHYS_PFN(x) ((x) >> L1_PAGETABLE_SHIFT)
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+#ifndef __ASSEMBLY__
+/* Definitions for machine and pseudophysical addresses. */
+#ifdef __i386__
+typedef unsigned long long paddr_t;
+typedef unsigned long long maddr_t;
+#else
+typedef unsigned long paddr_t;
+typedef unsigned long maddr_t;
+#endif
+
+extern unsigned long *phys_to_machine_mapping;
+extern char _text, _etext, _erodata, _edata, _end;
+extern unsigned long mfn_zero;
+#define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
+static __inline__ maddr_t phys_to_machine(paddr_t phys)
+{
+ maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
+ machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK);
+ return machine;
+}
+
+#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
+static __inline__ paddr_t machine_to_phys(maddr_t machine)
+{
+ paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
+ phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
+ return phys;
+}
+#endif
+
+#define VIRT_START ((unsigned long)&_text)
+
+#define to_phys(x) ((unsigned long)(x)-VIRT_START)
+#define to_virt(x) ((void *)((unsigned long)(x)+VIRT_START))
+
+#define virt_to_pfn(_virt) (PFN_DOWN(to_phys(_virt)))
+#define virt_to_mfn(_virt) (pfn_to_mfn(virt_to_pfn(_virt)))
+#define mach_to_virt(_mach) (to_virt(machine_to_phys(_mach)))
+#define virt_to_mach(_virt) (phys_to_machine(to_phys(_virt)))
+#define mfn_to_virt(_mfn) (to_virt(mfn_to_pfn(_mfn) << PAGE_SHIFT))
+#define pfn_to_virt(_pfn) (to_virt((_pfn) << PAGE_SHIFT))
+
+/* Pagetable walking. */
+#define pte_to_mfn(_pte) (((_pte) & (PADDR_MASK&PAGE_MASK)) >> L1_PAGETABLE_SHIFT)
+#define pte_to_virt(_pte) to_virt(mfn_to_pfn(pte_to_mfn(_pte)) << PAGE_SHIFT)
+
+
+#define PT_BASE ((pgentry_t *)start_info.pt_base)
+
+#ifdef __x86_64__
+#define virtual_to_l3(_virt) ((pgentry_t *)pte_to_virt(PT_BASE[l4_table_offset(_virt)]))
+#else
+#define virtual_to_l3(_virt) PT_BASE
+#endif
+
+#define virtual_to_l2(_virt) ({ \
+ unsigned long __virt2 = (_virt); \
+ (pgentry_t *) pte_to_virt(virtual_to_l3(__virt2)[l3_table_offset(__virt2)]); \
+})
+
+#define virtual_to_l1(_virt) ({ \
+ unsigned long __virt1 = (_virt); \
+ (pgentry_t *) pte_to_virt(virtual_to_l2(__virt1)[l2_table_offset(__virt1)]); \
+})
+
+#define virtual_to_pte(_virt) ({ \
+ unsigned long __virt0 = (unsigned long) (_virt); \
+ virtual_to_l1(__virt0)[l1_table_offset(__virt0)]; \
+})
+#define virtual_to_mfn(_virt) pte_to_mfn(virtual_to_pte(_virt))
+
+#define map_frames(f, n) map_frames_ex(f, n, 1, 0, 1, DOMID_SELF, NULL, L1_PROT)
+#define map_zero(n, a) map_frames_ex(&mfn_zero, n, 0, 0, a, DOMID_SELF, NULL, L1_PROT_RO)
+#define do_map_zero(start, n) do_map_frames(start, &mfn_zero, n, 0, 0, DOMID_SELF, NULL, L1_PROT_RO)
+
+pgentry_t *need_pgt(unsigned long addr);
+
+#endif /* _ARCH_MM_H_ */
--- /dev/null
+
+#ifndef __ARCH_SCHED_H__
+#define __ARCH_SCHED_H__
+
+#include "arch_limits.h"
+
+static inline struct thread* get_current(void)
+{
+ struct thread **current;
+#ifdef __i386__
+ register unsigned long sp asm("esp");
+#else
+ register unsigned long sp asm("rsp");
+#endif
+ current = (void *)(unsigned long)(sp & ~(__STACK_SIZE-1));
+ return *current;
+}
+
+extern void __arch_switch_threads(unsigned long *prevctx, unsigned long *nextctx);
+
+#define arch_switch_threads(prev,next) __arch_switch_threads(&(prev)->sp, &(next)->sp)
+
+
+
+#endif /* __ARCH_SCHED_H__ */
--- /dev/null
+
+
+#ifndef __ARCH_ASM_SPINLOCK_H
+#define __ARCH_ASM_SPINLOCK_H
+
+#include <mini-os/lib.h>
+#include "os.h"
+
+
+#define ARCH_SPIN_LOCK_UNLOCKED { 1 }
+
+/*
+ * Simple spin lock operations. There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions. They have a cost.
+ */
+
+#define arch_spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) <= 0)
+#define arch_spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
+
+#define spin_lock_string \
+ "1:\n" \
+ LOCK \
+ "decb %0\n\t" \
+ "jns 3f\n" \
+ "2:\t" \
+ "rep;nop\n\t" \
+ "cmpb $0,%0\n\t" \
+ "jle 2b\n\t" \
+ "jmp 1b\n" \
+ "3:\n\t"
+
+#define spin_lock_string_flags \
+ "1:\n" \
+ LOCK \
+ "decb %0\n\t" \
+ "jns 4f\n\t" \
+ "2:\t" \
+ "testl $0x200, %1\n\t" \
+ "jz 3f\n\t" \
+ "#sti\n\t" \
+ "3:\t" \
+ "rep;nop\n\t" \
+ "cmpb $0, %0\n\t" \
+ "jle 3b\n\t" \
+ "#cli\n\t" \
+ "jmp 1b\n" \
+ "4:\n\t"
+
+/*
+ * This works. Despite all the confusion.
+ * (except on PPro SMP or if we are using OOSTORE)
+ * (PPro errata 66, 92)
+ */
+
+#define spin_unlock_string \
+ "xchgb %b0, %1" \
+ :"=q" (oldval), "=m" (lock->slock) \
+ :"0" (oldval) : "memory"
+
+static inline void _raw_spin_unlock(spinlock_t *lock)
+{
+ char oldval = ARCH_SPIN_LOCK_UNLOCKED;
+ __asm__ __volatile__(
+ spin_unlock_string
+ );
+}
+
+static inline int _raw_spin_trylock(spinlock_t *lock)
+{
+ char oldval;
+ __asm__ __volatile__(
+ "xchgb %b0,%1\n"
+ :"=q" (oldval), "=m" (lock->slock)
+ :"0" (0) : "memory");
+ return oldval > 0;
+}
+
+static inline void _raw_spin_lock(spinlock_t *lock)
+{
+ __asm__ __volatile__(
+ spin_lock_string
+ :"=m" (lock->slock) : : "memory");
+}
+
+static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
+{
+ __asm__ __volatile__(
+ spin_lock_string_flags
+ :"=m" (lock->slock) : "r" (flags) : "memory");
+}
+
+#endif
--- /dev/null
+/******************************************************************************
+ * os.h
+ *
+ * random collection of macros and definition
+ */
+
+#ifndef _OS_H_
+#define _OS_H_
+
+#define smp_processor_id() 0
+
+
+#ifndef __ASSEMBLY__
+#include <mini-os/compiler.h>
+#include <mini-os/types.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/kernel.h>
+#include <xen/xsm/flask_op.h>
+
+#define USED __attribute__ ((used))
+
+#define BUG do_exit
+
+#endif
+#include <xen/xen.h>
+
+
+
+#define __KERNEL_CS FLAT_KERNEL_CS
+#define __KERNEL_DS FLAT_KERNEL_DS
+#define __KERNEL_SS FLAT_KERNEL_SS
+
+#define TRAP_divide_error 0
+#define TRAP_debug 1
+#define TRAP_nmi 2
+#define TRAP_int3 3
+#define TRAP_overflow 4
+#define TRAP_bounds 5
+#define TRAP_invalid_op 6
+#define TRAP_no_device 7
+#define TRAP_double_fault 8
+#define TRAP_copro_seg 9
+#define TRAP_invalid_tss 10
+#define TRAP_no_segment 11
+#define TRAP_stack_error 12
+#define TRAP_gp_fault 13
+#define TRAP_page_fault 14
+#define TRAP_spurious_int 15
+#define TRAP_copro_error 16
+#define TRAP_alignment_check 17
+#define TRAP_machine_check 18
+#define TRAP_simd_error 19
+#define TRAP_deferred_nmi 31
+
+/* Everything below this point is not included by assembler (.S) files. */
+#ifndef __ASSEMBLY__
+
+extern shared_info_t *HYPERVISOR_shared_info;
+
+void trap_init(void);
+void trap_fini(void);
+
+void arch_fini(void);
+
+
+
+
+
+/*
+ * The use of 'barrier' in the following reflects their use as local-lock
+ * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following
+ * critical operations are executed. All critical operations must complete
+ * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also
+ * includes these barriers, for example.
+ */
+
+#define __cli() \
+do { \
+ vcpu_info_t *_vcpu; \
+ _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
+ _vcpu->evtchn_upcall_mask = 1; \
+ barrier(); \
+} while (0)
+
+#define __sti() \
+do { \
+ vcpu_info_t *_vcpu; \
+ barrier(); \
+ _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
+ _vcpu->evtchn_upcall_mask = 0; \
+ barrier(); /* unmask then check (avoid races) */ \
+ if ( unlikely(_vcpu->evtchn_upcall_pending) ) \
+ force_evtchn_callback(); \
+} while (0)
+
+#define __save_flags(x) \
+do { \
+ vcpu_info_t *_vcpu; \
+ _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
+ (x) = _vcpu->evtchn_upcall_mask; \
+} while (0)
+
+#define __restore_flags(x) \
+do { \
+ vcpu_info_t *_vcpu; \
+ barrier(); \
+ _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
+ if ((_vcpu->evtchn_upcall_mask = (x)) == 0) { \
+ barrier(); /* unmask then check (avoid races) */ \
+ if ( unlikely(_vcpu->evtchn_upcall_pending) ) \
+ force_evtchn_callback(); \
+ }\
+} while (0)
+
+#define safe_halt() ((void)0)
+
+#define __save_and_cli(x) \
+do { \
+ vcpu_info_t *_vcpu; \
+ _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
+ (x) = _vcpu->evtchn_upcall_mask; \
+ _vcpu->evtchn_upcall_mask = 1; \
+ barrier(); \
+} while (0)
+
+#define local_irq_save(x) __save_and_cli(x)
+#define local_irq_restore(x) __restore_flags(x)
+#define local_save_flags(x) __save_flags(x)
+#define local_irq_disable() __cli()
+#define local_irq_enable() __sti()
+
+#define irqs_disabled() \
+ HYPERVISOR_shared_info->vcpu_info[smp_processor_id()].evtchn_upcall_mask
+
+/* This is a barrier for the compiler only, NOT the processor! */
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+#if defined(__i386__)
+#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
+#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
+#define wmb() __asm__ __volatile__ ("": : :"memory")
+#elif defined(__x86_64__)
+#define mb() __asm__ __volatile__ ("mfence":::"memory")
+#define rmb() __asm__ __volatile__ ("lfence":::"memory")
+#define wmb() __asm__ __volatile__ ("sfence" ::: "memory") /* From CONFIG_UNORDERED_IO (linux) */
+#endif
+
+
+#define LOCK_PREFIX ""
+#define LOCK ""
+#define ADDR (*(volatile long *) addr)
+/*
+ * Make sure gcc doesn't try to be clever and move things around
+ * on us. We need to use _exactly_ the address the user gave us,
+ * not some alias that contains the same information.
+ */
+typedef struct { volatile int counter; } atomic_t;
+
+
+/************************** i386 *******************************/
+#ifdef __INSIDE_MINIOS__
+#if defined (__i386__)
+
+#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((struct __xchg_dummy *)(x))
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+ switch (size) {
+ case 1:
+ __asm__ __volatile__("xchgb %b0,%1"
+ :"=q" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ case 2:
+ __asm__ __volatile__("xchgw %w0,%1"
+ :"=r" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ case 4:
+ __asm__ __volatile__("xchgl %0,%1"
+ :"=r" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ }
+ return x;
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It can be reorderdered on other architectures other than x86.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_clear_bit(int nr, volatile unsigned long * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__( LOCK
+ "btrl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"=m" (ADDR)
+ :"Ir" (nr) : "memory");
+ return oldbit;
+}
+
+static inline int constant_test_bit(int nr, const volatile unsigned long *addr)
+{
+ return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0;
+}
+
+static inline int variable_test_bit(int nr, const volatile unsigned long * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__(
+ "btl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit)
+ :"m" (ADDR),"Ir" (nr));
+ return oldbit;
+}
+
+#define test_bit(nr,addr) \
+(__builtin_constant_p(nr) ? \
+ constant_test_bit((nr),(addr)) : \
+ variable_test_bit((nr),(addr)))
+
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered. See __set_bit()
+ * if you do not require the atomic guarantees.
+ *
+ * Note: there are no guarantees that this function will not be reordered
+ * on non x86 architectures, so if you are writting portable code,
+ * make sure not to rely on its reordering guarantees.
+ *
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static inline void set_bit(int nr, volatile unsigned long * addr)
+{
+ __asm__ __volatile__( LOCK
+ "btsl %1,%0"
+ :"=m" (ADDR)
+ :"Ir" (nr));
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered. However, it does
+ * not contain a memory barrier, so if it is used for locking purposes,
+ * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * in order to ensure changes are visible on other processors.
+ */
+static inline void clear_bit(int nr, volatile unsigned long * addr)
+{
+ __asm__ __volatile__( LOCK
+ "btrl %1,%0"
+ :"=m" (ADDR)
+ :"Ir" (nr));
+}
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+ __asm__("bsfl %1,%0"
+ :"=r" (word)
+ :"rm" (word));
+ return word;
+}
+
+
+/*
+ * These have to be done with inline assembly: that way the bit-setting
+ * is guaranteed to be atomic. All bit operations return 0 if the bit
+ * was cleared before the operation and != 0 if it was not.
+ *
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ */
+#define ADDR (*(volatile long *) addr)
+
+#define rdtscll(val) \
+ __asm__ __volatile__("rdtsc" : "=A" (val))
+
+
+
+#elif defined(__x86_64__)/* ifdef __i386__ */
+/************************** x86_84 *******************************/
+
+#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
+#define __xg(x) ((volatile long *)(x))
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+ switch (size) {
+ case 1:
+ __asm__ __volatile__("xchgb %b0,%1"
+ :"=q" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ case 2:
+ __asm__ __volatile__("xchgw %w0,%1"
+ :"=r" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ case 4:
+ __asm__ __volatile__("xchgl %k0,%1"
+ :"=r" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ case 8:
+ __asm__ __volatile__("xchgq %0,%1"
+ :"=r" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ }
+ return x;
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__( LOCK_PREFIX
+ "btrl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"=m" (ADDR)
+ :"dIr" (nr) : "memory");
+ return oldbit;
+}
+
+static __inline__ int constant_test_bit(int nr, const volatile void * addr)
+{
+ return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
+}
+
+static __inline__ int variable_test_bit(int nr, volatile const void * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__(
+ "btl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit)
+ :"m" (ADDR),"dIr" (nr));
+ return oldbit;
+}
+
+#define test_bit(nr,addr) \
+(__builtin_constant_p(nr) ? \
+ constant_test_bit((nr),(addr)) : \
+ variable_test_bit((nr),(addr)))
+
+
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered. See __set_bit()
+ * if you do not require the atomic guarantees.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static __inline__ void set_bit(int nr, volatile void * addr)
+{
+ __asm__ __volatile__( LOCK_PREFIX
+ "btsl %1,%0"
+ :"=m" (ADDR)
+ :"dIr" (nr) : "memory");
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered. However, it does
+ * not contain a memory barrier, so if it is used for locking purposes,
+ * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * in order to ensure changes are visible on other processors.
+ */
+static __inline__ void clear_bit(int nr, volatile void * addr)
+{
+ __asm__ __volatile__( LOCK_PREFIX
+ "btrl %1,%0"
+ :"=m" (ADDR)
+ :"dIr" (nr));
+}
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static __inline__ unsigned long __ffs(unsigned long word)
+{
+ __asm__("bsfq %1,%0"
+ :"=r" (word)
+ :"rm" (word));
+ return word;
+}
+
+#define ADDR (*(volatile long *) addr)
+
+#define rdtscll(val) do { \
+ unsigned int __a,__d; \
+ asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
+ (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
+} while(0)
+
+#define wrmsr(msr,val1,val2) \
+ __asm__ __volatile__("wrmsr" \
+ : /* no outputs */ \
+ : "c" (msr), "a" (val1), "d" (val2))
+
+#define wrmsrl(msr,val) wrmsr(msr,(uint32_t)((uint64_t)(val)),((uint64_t)(val))>>32)
+
+
+#else /* ifdef __x86_64__ */
+#error "Unsupported architecture"
+#endif
+#endif /* ifdef __INSIDE_MINIOS */
+
+/********************* common i386 and x86_64 ****************************/
+struct __synch_xchg_dummy { unsigned long a[100]; };
+#define __synch_xg(x) ((struct __synch_xchg_dummy *)(x))
+
+#define synch_cmpxchg(ptr, old, new) \
+((__typeof__(*(ptr)))__synch_cmpxchg((ptr),\
+ (unsigned long)(old), \
+ (unsigned long)(new), \
+ sizeof(*(ptr))))
+
+static inline unsigned long __synch_cmpxchg(volatile void *ptr,
+ unsigned long old,
+ unsigned long new, int size)
+{
+ unsigned long prev;
+ switch (size) {
+ case 1:
+ __asm__ __volatile__("lock; cmpxchgb %b1,%2"
+ : "=a"(prev)
+ : "q"(new), "m"(*__synch_xg(ptr)),
+ "0"(old)
+ : "memory");
+ return prev;
+ case 2:
+ __asm__ __volatile__("lock; cmpxchgw %w1,%2"
+ : "=a"(prev)
+ : "r"(new), "m"(*__synch_xg(ptr)),
+ "0"(old)
+ : "memory");
+ return prev;
+#ifdef __x86_64__
+ case 4:
+ __asm__ __volatile__("lock; cmpxchgl %k1,%2"
+ : "=a"(prev)
+ : "r"(new), "m"(*__synch_xg(ptr)),
+ "0"(old)
+ : "memory");
+ return prev;
+ case 8:
+ __asm__ __volatile__("lock; cmpxchgq %1,%2"
+ : "=a"(prev)
+ : "r"(new), "m"(*__synch_xg(ptr)),
+ "0"(old)
+ : "memory");
+ return prev;
+#else
+ case 4:
+ __asm__ __volatile__("lock; cmpxchgl %1,%2"
+ : "=a"(prev)
+ : "r"(new), "m"(*__synch_xg(ptr)),
+ "0"(old)
+ : "memory");
+ return prev;
+#endif
+ }
+ return old;
+}
+
+
+static __inline__ void synch_set_bit(int nr, volatile void * addr)
+{
+ __asm__ __volatile__ (
+ "lock btsl %1,%0"
+ : "=m" (ADDR) : "Ir" (nr) : "memory" );
+}
+
+static __inline__ void synch_clear_bit(int nr, volatile void * addr)
+{
+ __asm__ __volatile__ (
+ "lock btrl %1,%0"
+ : "=m" (ADDR) : "Ir" (nr) : "memory" );
+}
+
+static __inline__ int synch_test_and_set_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+ __asm__ __volatile__ (
+ "lock btsl %2,%1\n\tsbbl %0,%0"
+ : "=r" (oldbit), "=m" (ADDR) : "Ir" (nr) : "memory");
+ return oldbit;
+}
+
+static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+ __asm__ __volatile__ (
+ "lock btrl %2,%1\n\tsbbl %0,%0"
+ : "=r" (oldbit), "=m" (ADDR) : "Ir" (nr) : "memory");
+ return oldbit;
+}
+
+static __inline__ int synch_const_test_bit(int nr, const volatile void * addr)
+{
+ return ((1UL << (nr & 31)) &
+ (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
+}
+
+static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+ __asm__ __volatile__ (
+ "btl %2,%1\n\tsbbl %0,%0"
+ : "=r" (oldbit) : "m" (ADDR), "Ir" (nr) );
+ return oldbit;
+}
+
+#define synch_test_bit(nr,addr) \
+(__builtin_constant_p(nr) ? \
+ synch_const_test_bit((nr),(addr)) : \
+ synch_var_test_bit((nr),(addr)))
+
+static inline int
+HYPERVISOR_xsm_op(
+ struct xen_flask_op *op)
+{
+ return _hypercall1(int, xsm_op, op);
+}
+
+#undef ADDR
+
+#endif /* not assembly */
+#endif /* _OS_H_ */
--- /dev/null
+/*
+ ****************************************************************************
+ * (C) 2005 - Grzegorz Milos - Intel Reseach Cambridge
+ ****************************************************************************
+ *
+ * File: traps.h
+ * Author: Grzegorz Milos (gm281@cam.ac.uk)
+ *
+ * Date: Jun 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: Deals with traps
+ *
+ ****************************************************************************
+ */
+
+#ifndef _TRAPS_H_
+#define _TRAPS_H_
+
+#ifdef __i386__
+struct pt_regs {
+ long ebx;
+ long ecx;
+ long edx;
+ long esi;
+ long edi;
+ long ebp;
+ long eax;
+ int xds;
+ int xes;
+ long orig_eax;
+ long eip;
+ int xcs;
+ long eflags;
+ long esp;
+ int xss;
+};
+#elif __x86_64__
+
+struct pt_regs {
+ unsigned long r15;
+ unsigned long r14;
+ unsigned long r13;
+ unsigned long r12;
+ unsigned long rbp;
+ unsigned long rbx;
+/* arguments: non interrupts/non tracing syscalls only save upto here*/
+ unsigned long r11;
+ unsigned long r10;
+ unsigned long r9;
+ unsigned long r8;
+ unsigned long rax;
+ unsigned long rcx;
+ unsigned long rdx;
+ unsigned long rsi;
+ unsigned long rdi;
+ unsigned long orig_rax;
+/* end of arguments */
+/* cpu exception frame or undefined */
+ unsigned long rip;
+ unsigned long cs;
+ unsigned long eflags;
+ unsigned long rsp;
+ unsigned long ss;
+/* top of stack page */
+};
+
+
+#endif
+
+void dump_regs(struct pt_regs *regs);
+void stack_walk(void);
+
+#define TRAP_PF_PROT 0x1
+#define TRAP_PF_WRITE 0x2
+#define TRAP_PF_USER 0x4
+
+#endif /* _TRAPS_H_ */
--- /dev/null
+#define __WORDSIZE 32
--- /dev/null
+/******************************************************************************
+ * hypercall-x86_32.h
+ *
+ * Copied from XenLinux.
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __HYPERCALL_X86_32_H__
+#define __HYPERCALL_X86_32_H__
+
+#include <xen/xen.h>
+#include <xen/sched.h>
+#include <xen/nmi.h>
+#include <mini-os/mm.h>
+
+typedef struct { unsigned long pte_low, pte_high; } pte_t;
+
+#define __pte(x) ({ unsigned long long _x = (x); \
+ ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
+
+#define __STR(x) #x
+#define STR(x) __STR(x)
+
+extern char hypercall_page[PAGE_SIZE];
+
+#define _hypercall0(type, name) \
+({ \
+ long __res; \
+ asm volatile ( \
+ "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
+ : "=a" (__res) \
+ : \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall1(type, name, a1) \
+({ \
+ long __res, __ign1; \
+ asm volatile ( \
+ "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
+ : "=a" (__res), "=b" (__ign1) \
+ : "1" ((long)(a1)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall2(type, name, a1, a2) \
+({ \
+ long __res, __ign1, __ign2; \
+ asm volatile ( \
+ "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \
+ : "1" ((long)(a1)), "2" ((long)(a2)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall3(type, name, a1, a2, a3) \
+({ \
+ long __res, __ign1, __ign2, __ign3; \
+ asm volatile ( \
+ "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3) \
+ : "1" ((long)(a1)), "2" ((long)(a2)), \
+ "3" ((long)(a3)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4) \
+({ \
+ long __res, __ign1, __ign2, __ign3, __ign4; \
+ asm volatile ( \
+ "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3), "=S" (__ign4) \
+ : "1" ((long)(a1)), "2" ((long)(a2)), \
+ "3" ((long)(a3)), "4" ((long)(a4)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
+({ \
+ long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \
+ asm volatile ( \
+ "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
+ : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
+ "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \
+ : "1" ((long)(a1)), "2" ((long)(a2)), \
+ "3" ((long)(a3)), "4" ((long)(a4)), \
+ "5" ((long)(a5)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+static inline int
+HYPERVISOR_set_trap_table(
+ trap_info_t *table)
+{
+ return _hypercall1(int, set_trap_table, table);
+}
+
+static inline int
+HYPERVISOR_mmu_update(
+ mmu_update_t *req, int count, int *success_count, domid_t domid)
+{
+ return _hypercall4(int, mmu_update, req, count, success_count, domid);
+}
+
+static inline int
+HYPERVISOR_mmuext_op(
+ struct mmuext_op *op, int count, int *success_count, domid_t domid)
+{
+ return _hypercall4(int, mmuext_op, op, count, success_count, domid);
+}
+
+static inline int
+HYPERVISOR_set_gdt(
+ unsigned long *frame_list, int entries)
+{
+ return _hypercall2(int, set_gdt, frame_list, entries);
+}
+
+static inline int
+HYPERVISOR_stack_switch(
+ unsigned long ss, unsigned long esp)
+{
+ return _hypercall2(int, stack_switch, ss, esp);
+}
+
+static inline int
+HYPERVISOR_set_callbacks(
+ unsigned long event_selector, unsigned long event_address,
+ unsigned long failsafe_selector, unsigned long failsafe_address)
+{
+ return _hypercall4(int, set_callbacks,
+ event_selector, event_address,
+ failsafe_selector, failsafe_address);
+}
+
+static inline int
+HYPERVISOR_fpu_taskswitch(
+ int set)
+{
+ return _hypercall1(int, fpu_taskswitch, set);
+}
+
+static inline int
+HYPERVISOR_sched_op(
+ int cmd, void *arg)
+{
+ return _hypercall2(int, sched_op, cmd, arg);
+}
+
+static inline int
+HYPERVISOR_shutdown(
+ unsigned int reason)
+{
+ struct sched_shutdown shutdown = { .reason = reason };
+ return _hypercall2(int, sched_op, SCHEDOP_shutdown, &shutdown);
+}
+
+static inline long
+HYPERVISOR_set_timer_op(
+ uint64_t timeout)
+{
+ unsigned long timeout_hi = (unsigned long)(timeout>>32);
+ unsigned long timeout_lo = (unsigned long)timeout;
+ return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
+}
+
+static inline int
+HYPERVISOR_set_debugreg(
+ int reg, unsigned long value)
+{
+ return _hypercall2(int, set_debugreg, reg, value);
+}
+
+static inline unsigned long
+HYPERVISOR_get_debugreg(
+ int reg)
+{
+ return _hypercall1(unsigned long, get_debugreg, reg);
+}
+
+static inline int
+HYPERVISOR_update_descriptor(
+ uint64_t ma, uint64_t desc)
+{
+ return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
+}
+
+static inline int
+HYPERVISOR_memory_op(
+ unsigned int cmd, void *arg)
+{
+ return _hypercall2(int, memory_op, cmd, arg);
+}
+
+static inline int
+HYPERVISOR_multicall(
+ void *call_list, int nr_calls)
+{
+ return _hypercall2(int, multicall, call_list, nr_calls);
+}
+
+static inline int
+HYPERVISOR_update_va_mapping(
+ unsigned long va, pte_t new_val, unsigned long flags)
+{
+ return _hypercall4(int, update_va_mapping, va,
+ new_val.pte_low, new_val.pte_high, flags);
+}
+
+static inline int
+HYPERVISOR_event_channel_op(
+ int cmd, void *op)
+{
+ return _hypercall2(int, event_channel_op, cmd, op);
+}
+
+static inline int
+HYPERVISOR_xen_version(
+ int cmd, void *arg)
+{
+ return _hypercall2(int, xen_version, cmd, arg);
+}
+
+static inline int
+HYPERVISOR_console_io(
+ int cmd, int count, char *str)
+{
+ return _hypercall3(int, console_io, cmd, count, str);
+}
+
+static inline int
+HYPERVISOR_physdev_op(
+ int cmd, void *physdev_op)
+{
+ return _hypercall2(int, physdev_op, cmd, physdev_op);
+}
+
+static inline int
+HYPERVISOR_grant_table_op(
+ unsigned int cmd, void *uop, unsigned int count)
+{
+ return _hypercall3(int, grant_table_op, cmd, uop, count);
+}
+
+static inline int
+HYPERVISOR_update_va_mapping_otherdomain(
+ unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+{
+ return _hypercall5(int, update_va_mapping_otherdomain, va,
+ new_val.pte_low, new_val.pte_high, flags, domid);
+}
+
+static inline int
+HYPERVISOR_vm_assist(
+ unsigned int cmd, unsigned int type)
+{
+ return _hypercall2(int, vm_assist, cmd, type);
+}
+
+static inline int
+HYPERVISOR_vcpu_op(
+ int cmd, int vcpuid, void *extra_args)
+{
+ return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
+}
+
+static inline int
+HYPERVISOR_suspend(
+ unsigned long srec)
+{
+ return _hypercall3(int, sched_op, SCHEDOP_shutdown,
+ SHUTDOWN_suspend, srec);
+}
+
+static inline int
+HYPERVISOR_nmi_op(
+ unsigned long op,
+ unsigned long arg)
+{
+ return _hypercall2(int, nmi_op, op, arg);
+}
+
+static inline int
+HYPERVISOR_sysctl(
+ unsigned long op)
+{
+ return _hypercall1(int, sysctl, op);
+}
+
+static inline int
+HYPERVISOR_domctl(
+ unsigned long op)
+{
+ return _hypercall1(int, domctl, op);
+}
+
+#endif /* __HYPERCALL_X86_32_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--- /dev/null
+#define __WORDSIZE 64
+#define __WORDSIZE_COMPAT32 1
--- /dev/null
+/******************************************************************************
+ * hypercall-x86_64.h
+ *
+ * Copied from XenLinux.
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * 64-bit updates:
+ * Benjamin Liu <benjamin.liu@intel.com>
+ * Jun Nakajima <jun.nakajima@intel.com>
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __HYPERCALL_X86_64_H__
+#define __HYPERCALL_X86_64_H__
+
+#include <xen/xen.h>
+#include <xen/sched.h>
+#include <mini-os/mm.h>
+
+typedef struct { unsigned long pte; } pte_t;
+
+#define __pte(x) ((pte_t) { (x) } )
+
+#define __STR(x) #x
+#define STR(x) __STR(x)
+
+extern char hypercall_page[PAGE_SIZE];
+
+#define _hypercall0(type, name) \
+({ \
+ long __res; \
+ asm volatile ( \
+ "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
+ : "=a" (__res) \
+ : \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall1(type, name, a1) \
+({ \
+ long __res, __ign1; \
+ asm volatile ( \
+ "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
+ : "=a" (__res), "=D" (__ign1) \
+ : "1" ((long)(a1)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall2(type, name, a1, a2) \
+({ \
+ long __res, __ign1, __ign2; \
+ asm volatile ( \
+ "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
+ : "=a" (__res), "=D" (__ign1), "=S" (__ign2) \
+ : "1" ((long)(a1)), "2" ((long)(a2)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall3(type, name, a1, a2, a3) \
+({ \
+ long __res, __ign1, __ign2, __ign3; \
+ asm volatile ( \
+ "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
+ : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \
+ "=d" (__ign3) \
+ : "1" ((long)(a1)), "2" ((long)(a2)), \
+ "3" ((long)(a3)) \
+ : "memory" ); \
+ (type)__res; \
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4) \
+({ \
+ long __res, __ign1, __ign2, __ign3; \
+ asm volatile ( \
+ "movq %7,%%r10; " \
+ "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
+ : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \
+ "=d" (__ign3) \
+ : "1" ((long)(a1)), "2" ((long)(a2)), \
+ "3" ((long)(a3)), "g" ((long)(a4)) \
+ : "memory", "r10" ); \
+ (type)__res; \
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
+({ \
+ long __res, __ign1, __ign2, __ign3; \
+ asm volatile ( \
+ "movq %7,%%r10; movq %8,%%r8; " \
+ "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
+ : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \
+ "=d" (__ign3) \
+ : "1" ((long)(a1)), "2" ((long)(a2)), \
+ "3" ((long)(a3)), "g" ((long)(a4)), \
+ "g" ((long)(a5)) \
+ : "memory", "r10", "r8" ); \
+ (type)__res; \
+})
+
+static inline int
+HYPERVISOR_set_trap_table(
+ trap_info_t *table)
+{
+ return _hypercall1(int, set_trap_table, table);
+}
+
+static inline int
+HYPERVISOR_mmu_update(
+ mmu_update_t *req, int count, int *success_count, domid_t domid)
+{
+ return _hypercall4(int, mmu_update, req, count, success_count, domid);
+}
+
+static inline int
+HYPERVISOR_mmuext_op(
+ struct mmuext_op *op, int count, int *success_count, domid_t domid)
+{
+ return _hypercall4(int, mmuext_op, op, count, success_count, domid);
+}
+
+static inline int
+HYPERVISOR_set_gdt(
+ unsigned long *frame_list, int entries)
+{
+ return _hypercall2(int, set_gdt, frame_list, entries);
+}
+
+static inline int
+HYPERVISOR_stack_switch(
+ unsigned long ss, unsigned long esp)
+{
+ return _hypercall2(int, stack_switch, ss, esp);
+}
+
+static inline int
+HYPERVISOR_set_callbacks(
+ unsigned long event_address, unsigned long failsafe_address,
+ unsigned long syscall_address)
+{
+ return _hypercall3(int, set_callbacks,
+ event_address, failsafe_address, syscall_address);
+}
+
+static inline int
+HYPERVISOR_fpu_taskswitch(
+ int set)
+{
+ return _hypercall1(int, fpu_taskswitch, set);
+}
+
+static inline int
+HYPERVISOR_sched_op(
+ int cmd, void *arg)
+{
+ return _hypercall2(int, sched_op, cmd, arg);
+}
+
+static inline int
+HYPERVISOR_shutdown(
+ unsigned int reason)
+{
+ struct sched_shutdown shutdown = { .reason = reason };
+ return _hypercall2(int, sched_op, SCHEDOP_shutdown, &shutdown);
+}
+
+static inline long
+HYPERVISOR_set_timer_op(
+ uint64_t timeout)
+{
+ return _hypercall1(long, set_timer_op, timeout);
+}
+
+static inline int
+HYPERVISOR_set_debugreg(
+ int reg, unsigned long value)
+{
+ return _hypercall2(int, set_debugreg, reg, value);
+}
+
+static inline unsigned long
+HYPERVISOR_get_debugreg(
+ int reg)
+{
+ return _hypercall1(unsigned long, get_debugreg, reg);
+}
+
+static inline int
+HYPERVISOR_update_descriptor(
+ unsigned long ma, unsigned long word)
+{
+ return _hypercall2(int, update_descriptor, ma, word);
+}
+
+static inline int
+HYPERVISOR_memory_op(
+ unsigned int cmd, void *arg)
+{
+ return _hypercall2(int, memory_op, cmd, arg);
+}
+
+static inline int
+HYPERVISOR_multicall(
+ void *call_list, int nr_calls)
+{
+ return _hypercall2(int, multicall, call_list, nr_calls);
+}
+
+static inline int
+HYPERVISOR_update_va_mapping(
+ unsigned long va, pte_t new_val, unsigned long flags)
+{
+ return _hypercall3(int, update_va_mapping, va, new_val.pte, flags);
+}
+
+static inline int
+HYPERVISOR_event_channel_op(
+ int cmd, void *op)
+{
+ return _hypercall2(int, event_channel_op, cmd, op);
+}
+
+static inline int
+HYPERVISOR_xen_version(
+ int cmd, void *arg)
+{
+ return _hypercall2(int, xen_version, cmd, arg);
+}
+
+static inline int
+HYPERVISOR_console_io(
+ int cmd, int count, char *str)
+{
+ return _hypercall3(int, console_io, cmd, count, str);
+}
+
+static inline int
+HYPERVISOR_physdev_op(
+ int cmd, void *physdev_op)
+{
+ return _hypercall2(int, physdev_op, cmd, physdev_op);
+}
+
+static inline int
+HYPERVISOR_grant_table_op(
+ unsigned int cmd, void *uop, unsigned int count)
+{
+ return _hypercall3(int, grant_table_op, cmd, uop, count);
+}
+
+static inline int
+HYPERVISOR_update_va_mapping_otherdomain(
+ unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+{
+ return _hypercall4(int, update_va_mapping_otherdomain, va,
+ new_val.pte, flags, domid);
+}
+
+static inline int
+HYPERVISOR_vm_assist(
+ unsigned int cmd, unsigned int type)
+{
+ return _hypercall2(int, vm_assist, cmd, type);
+}
+
+static inline int
+HYPERVISOR_vcpu_op(
+ int cmd, int vcpuid, void *extra_args)
+{
+ return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
+}
+
+static inline int
+HYPERVISOR_set_segment_base(
+ int reg, unsigned long value)
+{
+ return _hypercall2(int, set_segment_base, reg, value);
+}
+
+static inline int
+HYPERVISOR_suspend(
+ unsigned long srec)
+{
+ return _hypercall3(int, sched_op, SCHEDOP_shutdown,
+ SHUTDOWN_suspend, srec);
+}
+
+static inline int
+HYPERVISOR_nmi_op(
+ unsigned long op,
+ unsigned long arg)
+{
+ return _hypercall2(int, nmi_op, op, arg);
+}
+
+static inline int
+HYPERVISOR_sysctl(
+ unsigned long op)
+{
+ return _hypercall1(int, sysctl, op);
+}
+
+static inline int
+HYPERVISOR_domctl(
+ unsigned long op)
+{
+ return _hypercall1(int, domctl, op);
+}
+
+#endif /* __HYPERCALL_X86_64_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--- /dev/null
+XEN NOTICE
+==========
+
+This copyright applies to all files within this subdirectory and its
+subdirectories:
+ include/public/*.h
+ include/public/hvm/*.h
+ include/public/io/*.h
+
+The intention is that these files can be freely copied into the source
+tree of an operating system when porting that OS to run on Xen. Doing
+so does *not* cause the OS to become subject to the terms of the GPL.
+
+All other files in the Xen source distribution are covered by version
+2 of the GNU General Public License except where explicitly stated
+otherwise within individual source files.
+
+ -- Keir Fraser (on behalf of the Xen team)
+
+=====================================================================
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
--- /dev/null
+/******************************************************************************
+ * arch-arm.h
+ *
+ * Guest OS interface to ARM Xen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright 2011 (C) Citrix Systems
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_ARM_H__
+#define __XEN_PUBLIC_ARCH_ARM_H__
+
+/*
+ * `incontents 50 arm_abi Hypercall Calling Convention
+ *
+ * A hypercall is issued using the ARM HVC instruction.
+ *
+ * A hypercall can take up to 5 arguments. These are passed in
+ * registers, the first argument in x0/r0 (for arm64/arm32 guests
+ * respectively irrespective of whether the underlying hypervisor is
+ * 32- or 64-bit), the second argument in x1/r1, the third in x2/r2,
+ * the forth in x3/r3 and the fifth in x4/r4.
+ *
+ * The hypercall number is passed in r12 (arm) or x16 (arm64). In both
+ * cases the relevant ARM procedure calling convention specifies this
+ * is an inter-procedure-call scratch register (e.g. for use in linker
+ * stubs). This use does not conflict with use during a hypercall.
+ *
+ * The HVC ISS must contain a Xen specific TAG: XEN_HYPERCALL_TAG.
+ *
+ * The return value is in x0/r0.
+ *
+ * The hypercall will clobber x16/r12 and the argument registers used
+ * by that hypercall (except r0 which is the return value) i.e. in
+ * addition to x16/r12 a 2 argument hypercall will clobber x1/r1 and a
+ * 4 argument hypercall will clobber x1/r1, x2/r2 and x3/r3.
+ *
+ * Parameter structs passed to hypercalls are laid out according to
+ * the Procedure Call Standard for the ARM Architecture (AAPCS, AKA
+ * EABI) and Procedure Call Standard for the ARM 64-bit Architecture
+ * (AAPCS64). Where there is a conflict the 64-bit standard should be
+ * used regardless of guest type. Structures which are passed as
+ * hypercall arguments are always little endian.
+ *
+ * All memory which is shared with other entities in the system
+ * (including the hypervisor and other guests) must reside in memory
+ * which is mapped as Normal Inner-cacheable. This applies to:
+ * - hypercall arguments passed via a pointer to guest memory.
+ * - memory shared via the grant table mechanism (including PV I/O
+ * rings etc).
+ * - memory shared with the hypervisor (struct shared_info, struct
+ * vcpu_info, the grant table, etc).
+ *
+ * Any Inner cache allocation strategy (Write-Back, Write-Through etc)
+ * is acceptable. There is no restriction on the Outer-cacheability.
+ */
+
+/*
+ * `incontents 55 arm_hcall Supported Hypercalls
+ *
+ * Xen on ARM makes extensive use of hardware facilities and therefore
+ * only a subset of the potential hypercalls are required.
+ *
+ * Since ARM uses second stage paging any machine/physical addresses
+ * passed to hypercalls are Guest Physical Addresses (Intermediate
+ * Physical Addresses) unless otherwise noted.
+ *
+ * The following hypercalls (and sub operations) are supported on the
+ * ARM platform. Other hypercalls should be considered
+ * unavailable/unsupported.
+ *
+ * HYPERVISOR_memory_op
+ * All generic sub-operations
+ *
+ * HYPERVISOR_domctl
+ * All generic sub-operations, with the exception of:
+ * * XEN_DOMCTL_irq_permission (not yet implemented)
+ *
+ * HYPERVISOR_sched_op
+ * All generic sub-operations, with the exception of:
+ * * SCHEDOP_block -- prefer wfi hardware instruction
+ *
+ * HYPERVISOR_console_io
+ * All generic sub-operations
+ *
+ * HYPERVISOR_xen_version
+ * All generic sub-operations
+ *
+ * HYPERVISOR_event_channel_op
+ * All generic sub-operations
+ *
+ * HYPERVISOR_physdev_op
+ * No sub-operations are currenty supported
+ *
+ * HYPERVISOR_sysctl
+ * All generic sub-operations, with the exception of:
+ * * XEN_SYSCTL_page_offline_op
+ * * XEN_SYSCTL_get_pmstat
+ * * XEN_SYSCTL_pm_op
+ *
+ * HYPERVISOR_hvm_op
+ * Exactly these sub-operations are supported:
+ * * HVMOP_set_param
+ * * HVMOP_get_param
+ *
+ * HYPERVISOR_grant_table_op
+ * All generic sub-operations
+ *
+ * HYPERVISOR_vcpu_op
+ * Exactly these sub-operations are supported:
+ * * VCPUOP_register_vcpu_info
+ * * VCPUOP_register_runstate_memory_area
+ *
+ *
+ * Other notes on the ARM ABI:
+ *
+ * - struct start_info is not exported to ARM guests.
+ *
+ * - struct shared_info is mapped by ARM guests using the
+ * HYPERVISOR_memory_op sub-op XENMEM_add_to_physmap, passing
+ * XENMAPSPACE_shared_info as space parameter.
+ *
+ * - All the per-cpu struct vcpu_info are mapped by ARM guests using the
+ * HYPERVISOR_vcpu_op sub-op VCPUOP_register_vcpu_info, including cpu0
+ * struct vcpu_info.
+ *
+ * - The grant table is mapped using the HYPERVISOR_memory_op sub-op
+ * XENMEM_add_to_physmap, passing XENMAPSPACE_grant_table as space
+ * parameter. The memory range specified under the Xen compatible
+ * hypervisor node on device tree can be used as target gpfn for the
+ * mapping.
+ *
+ * - Xenstore is initialized by using the two hvm_params
+ * HVM_PARAM_STORE_PFN and HVM_PARAM_STORE_EVTCHN. They can be read
+ * with the HYPERVISOR_hvm_op sub-op HVMOP_get_param.
+ *
+ * - The paravirtualized console is initialized by using the two
+ * hvm_params HVM_PARAM_CONSOLE_PFN and HVM_PARAM_CONSOLE_EVTCHN. They
+ * can be read with the HYPERVISOR_hvm_op sub-op HVMOP_get_param.
+ *
+ * - Event channel notifications are delivered using the percpu GIC
+ * interrupt specified under the Xen compatible hypervisor node on
+ * device tree.
+ *
+ * - The device tree Xen compatible node is fully described under Linux
+ * at Documentation/devicetree/bindings/arm/xen.txt.
+ */
+
+#define XEN_HYPERCALL_TAG 0XEA1
+
+#define uint64_aligned_t uint64_t __attribute__((aligned(8)))
+
+#ifndef __ASSEMBLY__
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
+ typedef union { type *p; unsigned long q; } \
+ __guest_handle_ ## name; \
+ typedef union { type *p; uint64_aligned_t q; } \
+ __guest_handle_64_ ## name;
+
+/*
+ * XEN_GUEST_HANDLE represents a guest pointer, when passed as a field
+ * in a struct in memory. On ARM is always 8 bytes sizes and 8 bytes
+ * aligned.
+ * XEN_GUEST_HANDLE_PARAM represents a guest pointer, when passed as an
+ * hypercall argument. It is 4 bytes on aarch32 and 8 bytes on aarch64.
+ */
+#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
+ ___DEFINE_XEN_GUEST_HANDLE(name, type); \
+ ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
+#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
+#define __XEN_GUEST_HANDLE(name) __guest_handle_64_ ## name
+#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name)
+#define XEN_GUEST_HANDLE_PARAM(name) __guest_handle_ ## name
+#define set_xen_guest_handle_raw(hnd, val) \
+ do { \
+ typeof(&(hnd)) _sxghr_tmp = &(hnd); \
+ _sxghr_tmp->q = 0; \
+ _sxghr_tmp->p = val; \
+ } while ( 0 )
+#ifdef __XEN_TOOLS__
+#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0)
+#endif
+#define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val)
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+/* Anonymous union includes both 32- and 64-bit names (e.g., r0/x0). */
+# define __DECL_REG(n64, n32) union { \
+ uint64_t n64; \
+ uint32_t n32; \
+ }
+#else
+/* Non-gcc sources must always use the proper 64-bit name (e.g., x0). */
+#define __DECL_REG(n64, n32) uint64_t n64
+#endif
+
+struct vcpu_guest_core_regs
+{
+ /* Aarch64 Aarch32 */
+ __DECL_REG(x0, r0_usr);
+ __DECL_REG(x1, r1_usr);
+ __DECL_REG(x2, r2_usr);
+ __DECL_REG(x3, r3_usr);
+ __DECL_REG(x4, r4_usr);
+ __DECL_REG(x5, r5_usr);
+ __DECL_REG(x6, r6_usr);
+ __DECL_REG(x7, r7_usr);
+ __DECL_REG(x8, r8_usr);
+ __DECL_REG(x9, r9_usr);
+ __DECL_REG(x10, r10_usr);
+ __DECL_REG(x11, r11_usr);
+ __DECL_REG(x12, r12_usr);
+
+ __DECL_REG(x13, sp_usr);
+ __DECL_REG(x14, lr_usr);
+
+ __DECL_REG(x15, __unused_sp_hyp);
+
+ __DECL_REG(x16, lr_irq);
+ __DECL_REG(x17, sp_irq);
+
+ __DECL_REG(x18, lr_svc);
+ __DECL_REG(x19, sp_svc);
+
+ __DECL_REG(x20, lr_abt);
+ __DECL_REG(x21, sp_abt);
+
+ __DECL_REG(x22, lr_und);
+ __DECL_REG(x23, sp_und);
+
+ __DECL_REG(x24, r8_fiq);
+ __DECL_REG(x25, r9_fiq);
+ __DECL_REG(x26, r10_fiq);
+ __DECL_REG(x27, r11_fiq);
+ __DECL_REG(x28, r12_fiq);
+
+ __DECL_REG(x29, sp_fiq);
+ __DECL_REG(x30, lr_fiq);
+
+ /* Return address and mode */
+ __DECL_REG(pc64, pc32); /* ELR_EL2 */
+ uint32_t cpsr; /* SPSR_EL2 */
+
+ union {
+ uint32_t spsr_el1; /* AArch64 */
+ uint32_t spsr_svc; /* AArch32 */
+ };
+
+ /* AArch32 guests only */
+ uint32_t spsr_fiq, spsr_irq, spsr_und, spsr_abt;
+
+ /* AArch64 guests only */
+ uint64_t sp_el0;
+ uint64_t sp_el1, elr_el1;
+};
+typedef struct vcpu_guest_core_regs vcpu_guest_core_regs_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_guest_core_regs_t);
+
+#undef __DECL_REG
+
+typedef uint64_t xen_pfn_t;
+#define PRI_xen_pfn PRIx64
+
+/* Maximum number of virtual CPUs in legacy multi-processor guests. */
+/* Only one. All other VCPUS must use VCPUOP_register_vcpu_info */
+#define XEN_LEGACY_MAX_VCPUS 1
+
+typedef uint64_t xen_ulong_t;
+#define PRI_xen_ulong PRIx64
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+struct vcpu_guest_context {
+#define _VGCF_online 0
+#define VGCF_online (1<<_VGCF_online)
+ uint32_t flags; /* VGCF_* */
+
+ struct vcpu_guest_core_regs user_regs; /* Core CPU registers */
+
+ uint32_t sctlr;
+ uint64_t ttbcr, ttbr0, ttbr1;
+};
+typedef struct vcpu_guest_context vcpu_guest_context_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
+#endif
+
+struct arch_vcpu_info {
+};
+typedef struct arch_vcpu_info arch_vcpu_info_t;
+
+struct arch_shared_info {
+};
+typedef struct arch_shared_info arch_shared_info_t;
+typedef uint64_t xen_callback_t;
+
+#endif
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+/* PSR bits (CPSR, SPSR) */
+
+#define PSR_THUMB (1<<5) /* Thumb Mode enable */
+#define PSR_FIQ_MASK (1<<6) /* Fast Interrupt mask */
+#define PSR_IRQ_MASK (1<<7) /* Interrupt mask */
+#define PSR_ABT_MASK (1<<8) /* Asynchronous Abort mask */
+#define PSR_BIG_ENDIAN (1<<9) /* arm32: Big Endian Mode */
+#define PSR_DBG_MASK (1<<9) /* arm64: Debug Exception mask */
+#define PSR_IT_MASK (0x0600fc00) /* Thumb If-Then Mask */
+#define PSR_JAZELLE (1<<24) /* Jazelle Mode */
+
+/* 32 bit modes */
+#define PSR_MODE_USR 0x10
+#define PSR_MODE_FIQ 0x11
+#define PSR_MODE_IRQ 0x12
+#define PSR_MODE_SVC 0x13
+#define PSR_MODE_MON 0x16
+#define PSR_MODE_ABT 0x17
+#define PSR_MODE_HYP 0x1a
+#define PSR_MODE_UND 0x1b
+#define PSR_MODE_SYS 0x1f
+
+/* 64 bit modes */
+#define PSR_MODE_BIT 0x10 /* Set iff AArch32 */
+#define PSR_MODE_EL3h 0x0d
+#define PSR_MODE_EL3t 0x0c
+#define PSR_MODE_EL2h 0x09
+#define PSR_MODE_EL2t 0x08
+#define PSR_MODE_EL1h 0x05
+#define PSR_MODE_EL1t 0x04
+#define PSR_MODE_EL0t 0x00
+
+#define PSR_GUEST32_INIT (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_SVC)
+#define PSR_GUEST64_INIT (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_EL1h)
+
+#define SCTLR_GUEST_INIT 0x00c50078
+
+/*
+ * Virtual machine platform (memory layout, interrupts)
+ *
+ * These are defined for consistency between the tools and the
+ * hypervisor. Guests must not rely on these hardcoded values but
+ * should instead use the FDT.
+ */
+
+/* Physical Address Space */
+
+/*
+ * vGIC mappings: Only one set of mapping is used by the guest.
+ * Therefore they can overlap.
+ */
+
+/* vGIC v2 mappings */
+#define GUEST_GICD_BASE 0x03001000ULL
+#define GUEST_GICD_SIZE 0x00001000ULL
+#define GUEST_GICC_BASE 0x03002000ULL
+#define GUEST_GICC_SIZE 0x00000100ULL
+
+/* vGIC v3 mappings */
+#define GUEST_GICV3_GICD_BASE 0x03001000ULL
+#define GUEST_GICV3_GICD_SIZE 0x00010000ULL
+
+#define GUEST_GICV3_RDIST_STRIDE 0x20000ULL
+#define GUEST_GICV3_RDIST_REGIONS 1
+
+#define GUEST_GICV3_GICR0_BASE 0x03020000ULL /* vCPU0 - vCPU7 */
+#define GUEST_GICV3_GICR0_SIZE 0x00100000ULL
+
+/*
+ * 16MB == 4096 pages reserved for guest to use as a region to map its
+ * grant table in.
+ */
+#define GUEST_GNTTAB_BASE 0x38000000ULL
+#define GUEST_GNTTAB_SIZE 0x01000000ULL
+
+#define GUEST_MAGIC_BASE 0x39000000ULL
+#define GUEST_MAGIC_SIZE 0x01000000ULL
+
+#define GUEST_RAM_BANKS 2
+
+#define GUEST_RAM0_BASE 0x40000000ULL /* 3GB of low RAM @ 1GB */
+#define GUEST_RAM0_SIZE 0xc0000000ULL
+
+#define GUEST_RAM1_BASE 0x0200000000ULL /* 1016GB of RAM @ 8GB */
+#define GUEST_RAM1_SIZE 0xfe00000000ULL
+
+#define GUEST_RAM_BASE GUEST_RAM0_BASE /* Lowest RAM address */
+/* Largest amount of actual RAM, not including holes */
+#define GUEST_RAM_MAX (GUEST_RAM0_SIZE + GUEST_RAM1_SIZE)
+/* Suitable for e.g. const uint64_t ramfoo[] = GUEST_RAM_BANK_FOOS; */
+#define GUEST_RAM_BANK_BASES { GUEST_RAM0_BASE, GUEST_RAM1_BASE }
+#define GUEST_RAM_BANK_SIZES { GUEST_RAM0_SIZE, GUEST_RAM1_SIZE }
+
+/* Interrupts */
+#define GUEST_TIMER_VIRT_PPI 27
+#define GUEST_TIMER_PHYS_S_PPI 29
+#define GUEST_TIMER_PHYS_NS_PPI 30
+#define GUEST_EVTCHN_PPI 31
+
+/* PSCI functions */
+#define PSCI_cpu_suspend 0
+#define PSCI_cpu_off 1
+#define PSCI_cpu_on 2
+#define PSCI_migrate 3
+
+#endif
+
+#endif /* __XEN_PUBLIC_ARCH_ARM_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/*
+ * Structure definitions for HVM state that is held by Xen and must
+ * be saved along with the domain's memory and device-model state.
+ *
+ * Copyright (c) 2012 Citrix Systems Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PUBLIC_HVM_SAVE_ARM_H__
+#define __XEN_PUBLIC_HVM_SAVE_ARM_H__
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * arch-x86/cpuid.h
+ *
+ * CPUID interface to Xen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2007 Citrix Systems, Inc.
+ *
+ * Authors:
+ * Keir Fraser <keir@xen.org>
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_X86_CPUID_H__
+#define __XEN_PUBLIC_ARCH_X86_CPUID_H__
+
+/*
+ * For compatibility with other hypervisor interfaces, the Xen cpuid leaves
+ * can be found at the first otherwise unused 0x100 aligned boundary starting
+ * from 0x40000000.
+ *
+ * e.g If viridian extensions are enabled for an HVM domain, the Xen cpuid
+ * leaves will start at 0x40000100
+ */
+
+#define XEN_CPUID_FIRST_LEAF 0x40000000
+#define XEN_CPUID_LEAF(i) (XEN_CPUID_FIRST_LEAF + (i))
+
+/*
+ * Leaf 1 (0x40000x00)
+ * EAX: Largest Xen-information leaf. All leaves up to an including @EAX
+ * are supported by the Xen host.
+ * EBX-EDX: "XenVMMXenVMM" signature, allowing positive identification
+ * of a Xen host.
+ */
+#define XEN_CPUID_SIGNATURE_EBX 0x566e6558 /* "XenV" */
+#define XEN_CPUID_SIGNATURE_ECX 0x65584d4d /* "MMXe" */
+#define XEN_CPUID_SIGNATURE_EDX 0x4d4d566e /* "nVMM" */
+
+/*
+ * Leaf 2 (0x40000x01)
+ * EAX[31:16]: Xen major version.
+ * EAX[15: 0]: Xen minor version.
+ * EBX-EDX: Reserved (currently all zeroes).
+ */
+
+/*
+ * Leaf 3 (0x40000x02)
+ * EAX: Number of hypercall transfer pages. This register is always guaranteed
+ * to specify one hypercall page.
+ * EBX: Base address of Xen-specific MSRs.
+ * ECX: Features 1. Unused bits are set to zero.
+ * EDX: Features 2. Unused bits are set to zero.
+ */
+
+/* Does the host support MMU_PT_UPDATE_PRESERVE_AD for this guest? */
+#define _XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD 0
+#define XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD (1u<<0)
+
+/*
+ * Leaf 5 (0x40000x04)
+ * HVM-specific features
+ * EAX: Features
+ * EBX: vcpu id (iff EAX has XEN_HVM_CPUID_VCPU_ID_PRESENT flag)
+ */
+#define XEN_HVM_CPUID_APIC_ACCESS_VIRT (1u << 0) /* Virtualized APIC registers */
+#define XEN_HVM_CPUID_X2APIC_VIRT (1u << 1) /* Virtualized x2APIC accesses */
+/* Memory mapped from other domains has valid IOMMU entries */
+#define XEN_HVM_CPUID_IOMMU_MAPPINGS (1u << 2)
+#define XEN_HVM_CPUID_VCPU_ID_PRESENT (1u << 3) /* vcpu id is present in EBX */
+
+#define XEN_CPUID_MAX_NUM_LEAVES 4
+
+#endif /* __XEN_PUBLIC_ARCH_X86_CPUID_H__ */
--- /dev/null
+/*
+ * Structure definitions for HVM state that is held by Xen and must
+ * be saved along with the domain's memory and device-model state.
+ *
+ * Copyright (c) 2007 XenSource Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PUBLIC_HVM_SAVE_X86_H__
+#define __XEN_PUBLIC_HVM_SAVE_X86_H__
+
+/*
+ * Save/restore header: general info about the save file.
+ */
+
+#define HVM_FILE_MAGIC 0x54381286
+#define HVM_FILE_VERSION 0x00000001
+
+struct hvm_save_header {
+ uint32_t magic; /* Must be HVM_FILE_MAGIC */
+ uint32_t version; /* File format version */
+ uint64_t changeset; /* Version of Xen that saved this file */
+ uint32_t cpuid; /* CPUID[0x01][%eax] on the saving machine */
+ uint32_t gtsc_khz; /* Guest's TSC frequency in kHz */
+};
+
+DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header);
+
+
+/*
+ * Processor
+ *
+ * Compat: Pre-3.4 didn't have msr_tsc_aux
+ */
+
+struct hvm_hw_cpu {
+ uint8_t fpu_regs[512];
+
+ uint64_t rax;
+ uint64_t rbx;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rbp;
+ uint64_t rsi;
+ uint64_t rdi;
+ uint64_t rsp;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+
+ uint64_t rip;
+ uint64_t rflags;
+
+ uint64_t cr0;
+ uint64_t cr2;
+ uint64_t cr3;
+ uint64_t cr4;
+
+ uint64_t dr0;
+ uint64_t dr1;
+ uint64_t dr2;
+ uint64_t dr3;
+ uint64_t dr6;
+ uint64_t dr7;
+
+ uint32_t cs_sel;
+ uint32_t ds_sel;
+ uint32_t es_sel;
+ uint32_t fs_sel;
+ uint32_t gs_sel;
+ uint32_t ss_sel;
+ uint32_t tr_sel;
+ uint32_t ldtr_sel;
+
+ uint32_t cs_limit;
+ uint32_t ds_limit;
+ uint32_t es_limit;
+ uint32_t fs_limit;
+ uint32_t gs_limit;
+ uint32_t ss_limit;
+ uint32_t tr_limit;
+ uint32_t ldtr_limit;
+ uint32_t idtr_limit;
+ uint32_t gdtr_limit;
+
+ uint64_t cs_base;
+ uint64_t ds_base;
+ uint64_t es_base;
+ uint64_t fs_base;
+ uint64_t gs_base;
+ uint64_t ss_base;
+ uint64_t tr_base;
+ uint64_t ldtr_base;
+ uint64_t idtr_base;
+ uint64_t gdtr_base;
+
+ uint32_t cs_arbytes;
+ uint32_t ds_arbytes;
+ uint32_t es_arbytes;
+ uint32_t fs_arbytes;
+ uint32_t gs_arbytes;
+ uint32_t ss_arbytes;
+ uint32_t tr_arbytes;
+ uint32_t ldtr_arbytes;
+
+ uint64_t sysenter_cs;
+ uint64_t sysenter_esp;
+ uint64_t sysenter_eip;
+
+ /* msr for em64t */
+ uint64_t shadow_gs;
+
+ /* msr content saved/restored. */
+ uint64_t msr_flags;
+ uint64_t msr_lstar;
+ uint64_t msr_star;
+ uint64_t msr_cstar;
+ uint64_t msr_syscall_mask;
+ uint64_t msr_efer;
+ uint64_t msr_tsc_aux;
+
+ /* guest's idea of what rdtsc() would return */
+ uint64_t tsc;
+
+ /* pending event, if any */
+ union {
+ uint32_t pending_event;
+ struct {
+ uint8_t pending_vector:8;
+ uint8_t pending_type:3;
+ uint8_t pending_error_valid:1;
+ uint32_t pending_reserved:19;
+ uint8_t pending_valid:1;
+ };
+ };
+ /* error code for pending event */
+ uint32_t error_code;
+};
+
+struct hvm_hw_cpu_compat {
+ uint8_t fpu_regs[512];
+
+ uint64_t rax;
+ uint64_t rbx;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rbp;
+ uint64_t rsi;
+ uint64_t rdi;
+ uint64_t rsp;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+
+ uint64_t rip;
+ uint64_t rflags;
+
+ uint64_t cr0;
+ uint64_t cr2;
+ uint64_t cr3;
+ uint64_t cr4;
+
+ uint64_t dr0;
+ uint64_t dr1;
+ uint64_t dr2;
+ uint64_t dr3;
+ uint64_t dr6;
+ uint64_t dr7;
+
+ uint32_t cs_sel;
+ uint32_t ds_sel;
+ uint32_t es_sel;
+ uint32_t fs_sel;
+ uint32_t gs_sel;
+ uint32_t ss_sel;
+ uint32_t tr_sel;
+ uint32_t ldtr_sel;
+
+ uint32_t cs_limit;
+ uint32_t ds_limit;
+ uint32_t es_limit;
+ uint32_t fs_limit;
+ uint32_t gs_limit;
+ uint32_t ss_limit;
+ uint32_t tr_limit;
+ uint32_t ldtr_limit;
+ uint32_t idtr_limit;
+ uint32_t gdtr_limit;
+
+ uint64_t cs_base;
+ uint64_t ds_base;
+ uint64_t es_base;
+ uint64_t fs_base;
+ uint64_t gs_base;
+ uint64_t ss_base;
+ uint64_t tr_base;
+ uint64_t ldtr_base;
+ uint64_t idtr_base;
+ uint64_t gdtr_base;
+
+ uint32_t cs_arbytes;
+ uint32_t ds_arbytes;
+ uint32_t es_arbytes;
+ uint32_t fs_arbytes;
+ uint32_t gs_arbytes;
+ uint32_t ss_arbytes;
+ uint32_t tr_arbytes;
+ uint32_t ldtr_arbytes;
+
+ uint64_t sysenter_cs;
+ uint64_t sysenter_esp;
+ uint64_t sysenter_eip;
+
+ /* msr for em64t */
+ uint64_t shadow_gs;
+
+ /* msr content saved/restored. */
+ uint64_t msr_flags;
+ uint64_t msr_lstar;
+ uint64_t msr_star;
+ uint64_t msr_cstar;
+ uint64_t msr_syscall_mask;
+ uint64_t msr_efer;
+ /*uint64_t msr_tsc_aux; COMPAT */
+
+ /* guest's idea of what rdtsc() would return */
+ uint64_t tsc;
+
+ /* pending event, if any */
+ union {
+ uint32_t pending_event;
+ struct {
+ uint8_t pending_vector:8;
+ uint8_t pending_type:3;
+ uint8_t pending_error_valid:1;
+ uint32_t pending_reserved:19;
+ uint8_t pending_valid:1;
+ };
+ };
+ /* error code for pending event */
+ uint32_t error_code;
+};
+
+static inline int _hvm_hw_fix_cpu(void *h) {
+
+ union hvm_hw_cpu_union {
+ struct hvm_hw_cpu nat;
+ struct hvm_hw_cpu_compat cmp;
+ } *ucpu = (union hvm_hw_cpu_union *)h;
+
+ /* If we copy from the end backwards, we should
+ * be able to do the modification in-place */
+ ucpu->nat.error_code = ucpu->cmp.error_code;
+ ucpu->nat.pending_event = ucpu->cmp.pending_event;
+ ucpu->nat.tsc = ucpu->cmp.tsc;
+ ucpu->nat.msr_tsc_aux = 0;
+
+ return 0;
+}
+
+DECLARE_HVM_SAVE_TYPE_COMPAT(CPU, 2, struct hvm_hw_cpu, \
+ struct hvm_hw_cpu_compat, _hvm_hw_fix_cpu);
+
+/*
+ * PIC
+ */
+
+struct hvm_hw_vpic {
+ /* IR line bitmasks. */
+ uint8_t irr;
+ uint8_t imr;
+ uint8_t isr;
+
+ /* Line IRx maps to IRQ irq_base+x */
+ uint8_t irq_base;
+
+ /*
+ * Where are we in ICW2-4 initialisation (0 means no init in progress)?
+ * Bits 0-1 (=x): Next write at A=1 sets ICW(x+1).
+ * Bit 2: ICW1.IC4 (1 == ICW4 included in init sequence)
+ * Bit 3: ICW1.SNGL (0 == ICW3 included in init sequence)
+ */
+ uint8_t init_state:4;
+
+ /* IR line with highest priority. */
+ uint8_t priority_add:4;
+
+ /* Reads from A=0 obtain ISR or IRR? */
+ uint8_t readsel_isr:1;
+
+ /* Reads perform a polling read? */
+ uint8_t poll:1;
+
+ /* Automatically clear IRQs from the ISR during INTA? */
+ uint8_t auto_eoi:1;
+
+ /* Automatically rotate IRQ priorities during AEOI? */
+ uint8_t rotate_on_auto_eoi:1;
+
+ /* Exclude slave inputs when considering in-service IRQs? */
+ uint8_t special_fully_nested_mode:1;
+
+ /* Special mask mode excludes masked IRs from AEOI and priority checks. */
+ uint8_t special_mask_mode:1;
+
+ /* Is this a master PIC or slave PIC? (NB. This is not programmable.) */
+ uint8_t is_master:1;
+
+ /* Edge/trigger selection. */
+ uint8_t elcr;
+
+ /* Virtual INT output. */
+ uint8_t int_output;
+};
+
+DECLARE_HVM_SAVE_TYPE(PIC, 3, struct hvm_hw_vpic);
+
+
+/*
+ * IO-APIC
+ */
+
+#define VIOAPIC_NUM_PINS 48 /* 16 ISA IRQs, 32 non-legacy PCI IRQS. */
+
+struct hvm_hw_vioapic {
+ uint64_t base_address;
+ uint32_t ioregsel;
+ uint32_t id;
+ union vioapic_redir_entry
+ {
+ uint64_t bits;
+ struct {
+ uint8_t vector;
+ uint8_t delivery_mode:3;
+ uint8_t dest_mode:1;
+ uint8_t delivery_status:1;
+ uint8_t polarity:1;
+ uint8_t remote_irr:1;
+ uint8_t trig_mode:1;
+ uint8_t mask:1;
+ uint8_t reserve:7;
+ uint8_t reserved[4];
+ uint8_t dest_id;
+ } fields;
+ } redirtbl[VIOAPIC_NUM_PINS];
+};
+
+DECLARE_HVM_SAVE_TYPE(IOAPIC, 4, struct hvm_hw_vioapic);
+
+
+/*
+ * LAPIC
+ */
+
+struct hvm_hw_lapic {
+ uint64_t apic_base_msr;
+ uint32_t disabled; /* VLAPIC_xx_DISABLED */
+ uint32_t timer_divisor;
+ uint64_t tdt_msr;
+};
+
+DECLARE_HVM_SAVE_TYPE(LAPIC, 5, struct hvm_hw_lapic);
+
+struct hvm_hw_lapic_regs {
+ uint8_t data[1024];
+};
+
+DECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 6, struct hvm_hw_lapic_regs);
+
+
+/*
+ * IRQs
+ */
+
+struct hvm_hw_pci_irqs {
+ /*
+ * Virtual interrupt wires for a single PCI bus.
+ * Indexed by: device*4 + INTx#.
+ */
+ union {
+ unsigned long i[16 / sizeof (unsigned long)]; /* DECLARE_BITMAP(i, 32*4); */
+ uint64_t pad[2];
+ };
+};
+
+DECLARE_HVM_SAVE_TYPE(PCI_IRQ, 7, struct hvm_hw_pci_irqs);
+
+struct hvm_hw_isa_irqs {
+ /*
+ * Virtual interrupt wires for ISA devices.
+ * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
+ */
+ union {
+ unsigned long i[1]; /* DECLARE_BITMAP(i, 16); */
+ uint64_t pad[1];
+ };
+};
+
+DECLARE_HVM_SAVE_TYPE(ISA_IRQ, 8, struct hvm_hw_isa_irqs);
+
+struct hvm_hw_pci_link {
+ /*
+ * PCI-ISA interrupt router.
+ * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
+ * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
+ * The router provides a programmable mapping from each link to a GSI.
+ */
+ uint8_t route[4];
+ uint8_t pad0[4];
+};
+
+DECLARE_HVM_SAVE_TYPE(PCI_LINK, 9, struct hvm_hw_pci_link);
+
+/*
+ * PIT
+ */
+
+struct hvm_hw_pit {
+ struct hvm_hw_pit_channel {
+ uint32_t count; /* can be 65536 */
+ uint16_t latched_count;
+ uint8_t count_latched;
+ uint8_t status_latched;
+ uint8_t status;
+ uint8_t read_state;
+ uint8_t write_state;
+ uint8_t write_latch;
+ uint8_t rw_mode;
+ uint8_t mode;
+ uint8_t bcd; /* not supported */
+ uint8_t gate; /* timer start */
+ } channels[3]; /* 3 x 16 bytes */
+ uint32_t speaker_data_on;
+ uint32_t pad0;
+};
+
+DECLARE_HVM_SAVE_TYPE(PIT, 10, struct hvm_hw_pit);
+
+
+/*
+ * RTC
+ */
+
+#define RTC_CMOS_SIZE 14
+struct hvm_hw_rtc {
+ /* CMOS bytes */
+ uint8_t cmos_data[RTC_CMOS_SIZE];
+ /* Index register for 2-part operations */
+ uint8_t cmos_index;
+ uint8_t pad0;
+};
+
+DECLARE_HVM_SAVE_TYPE(RTC, 11, struct hvm_hw_rtc);
+
+
+/*
+ * HPET
+ */
+
+#define HPET_TIMER_NUM 3 /* 3 timers supported now */
+struct hvm_hw_hpet {
+ /* Memory-mapped, software visible registers */
+ uint64_t capability; /* capabilities */
+ uint64_t res0; /* reserved */
+ uint64_t config; /* configuration */
+ uint64_t res1; /* reserved */
+ uint64_t isr; /* interrupt status reg */
+ uint64_t res2[25]; /* reserved */
+ uint64_t mc64; /* main counter */
+ uint64_t res3; /* reserved */
+ struct { /* timers */
+ uint64_t config; /* configuration/cap */
+ uint64_t cmp; /* comparator */
+ uint64_t fsb; /* FSB route, not supported now */
+ uint64_t res4; /* reserved */
+ } timers[HPET_TIMER_NUM];
+ uint64_t res5[4*(24-HPET_TIMER_NUM)]; /* reserved, up to 0x3ff */
+
+ /* Hidden register state */
+ uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */
+};
+
+DECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet);
+
+
+/*
+ * PM timer
+ */
+
+struct hvm_hw_pmtimer {
+ uint32_t tmr_val; /* PM_TMR_BLK.TMR_VAL: 32bit free-running counter */
+ uint16_t pm1a_sts; /* PM1a_EVT_BLK.PM1a_STS: status register */
+ uint16_t pm1a_en; /* PM1a_EVT_BLK.PM1a_EN: enable register */
+};
+
+DECLARE_HVM_SAVE_TYPE(PMTIMER, 13, struct hvm_hw_pmtimer);
+
+/*
+ * MTRR MSRs
+ */
+
+struct hvm_hw_mtrr {
+#define MTRR_VCNT 8
+#define NUM_FIXED_MSR 11
+ uint64_t msr_pat_cr;
+ /* mtrr physbase & physmask msr pair*/
+ uint64_t msr_mtrr_var[MTRR_VCNT*2];
+ uint64_t msr_mtrr_fixed[NUM_FIXED_MSR];
+ uint64_t msr_mtrr_cap;
+ uint64_t msr_mtrr_def_type;
+};
+
+DECLARE_HVM_SAVE_TYPE(MTRR, 14, struct hvm_hw_mtrr);
+
+/*
+ * The save area of XSAVE/XRSTOR.
+ */
+
+struct hvm_hw_cpu_xsave {
+ uint64_t xfeature_mask; /* Ignored */
+ uint64_t xcr0; /* Updated by XSETBV */
+ uint64_t xcr0_accum; /* Updated by XSETBV */
+ struct {
+ struct { char x[512]; } fpu_sse;
+
+ struct {
+ uint64_t xstate_bv; /* Updated by XRSTOR */
+ uint64_t reserved[7];
+ } xsave_hdr; /* The 64-byte header */
+
+ struct { char x[0]; } ymm; /* YMM */
+ } save_area;
+};
+
+#define CPU_XSAVE_CODE 16
+
+/*
+ * Viridian hypervisor context.
+ */
+
+struct hvm_viridian_domain_context {
+ uint64_t hypercall_gpa;
+ uint64_t guest_os_id;
+ uint64_t time_ref_count;
+ uint64_t reference_tsc;
+};
+
+DECLARE_HVM_SAVE_TYPE(VIRIDIAN_DOMAIN, 15, struct hvm_viridian_domain_context);
+
+struct hvm_viridian_vcpu_context {
+ uint64_t apic_assist;
+};
+
+DECLARE_HVM_SAVE_TYPE(VIRIDIAN_VCPU, 17, struct hvm_viridian_vcpu_context);
+
+struct hvm_vmce_vcpu {
+ uint64_t caps;
+ uint64_t mci_ctl2_bank0;
+ uint64_t mci_ctl2_bank1;
+};
+
+DECLARE_HVM_SAVE_TYPE(VMCE_VCPU, 18, struct hvm_vmce_vcpu);
+
+struct hvm_tsc_adjust {
+ uint64_t tsc_adjust;
+};
+
+DECLARE_HVM_SAVE_TYPE(TSC_ADJUST, 19, struct hvm_tsc_adjust);
+
+
+struct hvm_msr {
+ uint32_t count;
+ struct hvm_one_msr {
+ uint32_t index;
+ uint32_t _rsvd;
+ uint64_t val;
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+ } msr[];
+#elif defined(__GNUC__)
+ } msr[0];
+#else
+ } msr[1 /* variable size */];
+#endif
+};
+
+#define CPU_MSR_CODE 20
+
+/*
+ * Largest type-code in use
+ */
+#define HVM_SAVE_CODE_MAX 20
+
+#endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * arch-x86/mca.h
+ *
+ * Contributed by Advanced Micro Devices, Inc.
+ * Author: Christoph Egger <Christoph.Egger@amd.com>
+ *
+ * Guest OS machine check interface to x86 Xen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/* Full MCA functionality has the following Usecases from the guest side:
+ *
+ * Must have's:
+ * 1. Dom0 and DomU register machine check trap callback handlers
+ * (already done via "set_trap_table" hypercall)
+ * 2. Dom0 registers machine check event callback handler
+ * (doable via EVTCHNOP_bind_virq)
+ * 3. Dom0 and DomU fetches machine check data
+ * 4. Dom0 wants Xen to notify a DomU
+ * 5. Dom0 gets DomU ID from physical address
+ * 6. Dom0 wants Xen to kill DomU (already done for "xm destroy")
+ *
+ * Nice to have's:
+ * 7. Dom0 wants Xen to deactivate a physical CPU
+ * This is better done as separate task, physical CPU hotplugging,
+ * and hypercall(s) should be sysctl's
+ * 8. Page migration proposed from Xen NUMA work, where Dom0 can tell Xen to
+ * move a DomU (or Dom0 itself) away from a malicious page
+ * producing correctable errors.
+ * 9. offlining physical page:
+ * Xen free's and never re-uses a certain physical page.
+ * 10. Testfacility: Allow Dom0 to write values into machine check MSR's
+ * and tell Xen to trigger a machine check
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_X86_MCA_H__
+#define __XEN_PUBLIC_ARCH_X86_MCA_H__
+
+/* Hypercall */
+#define __HYPERVISOR_mca __HYPERVISOR_arch_0
+
+/*
+ * The xen-unstable repo has interface version 0x03000001; out interface
+ * is incompatible with that and any future minor revisions, so we
+ * choose a different version number range that is numerically less
+ * than that used in xen-unstable.
+ */
+#define XEN_MCA_INTERFACE_VERSION 0x01ecc003
+
+/* IN: Dom0 calls hypercall to retrieve nonurgent telemetry */
+#define XEN_MC_NONURGENT 0x0001
+/* IN: Dom0/DomU calls hypercall to retrieve urgent telemetry */
+#define XEN_MC_URGENT 0x0002
+/* IN: Dom0 acknowledges previosly-fetched telemetry */
+#define XEN_MC_ACK 0x0004
+
+/* OUT: All is ok */
+#define XEN_MC_OK 0x0
+/* OUT: Domain could not fetch data. */
+#define XEN_MC_FETCHFAILED 0x1
+/* OUT: There was no machine check data to fetch. */
+#define XEN_MC_NODATA 0x2
+/* OUT: Between notification time and this hypercall an other
+ * (most likely) correctable error happened. The fetched data,
+ * does not match the original machine check data. */
+#define XEN_MC_NOMATCH 0x4
+
+/* OUT: DomU did not register MC NMI handler. Try something else. */
+#define XEN_MC_CANNOTHANDLE 0x8
+/* OUT: Notifying DomU failed. Retry later or try something else. */
+#define XEN_MC_NOTDELIVERED 0x10
+/* Note, XEN_MC_CANNOTHANDLE and XEN_MC_NOTDELIVERED are mutually exclusive. */
+
+
+#ifndef __ASSEMBLY__
+
+#define VIRQ_MCA VIRQ_ARCH_0 /* G. (DOM0) Machine Check Architecture */
+
+/*
+ * Machine Check Architecure:
+ * structs are read-only and used to report all kinds of
+ * correctable and uncorrectable errors detected by the HW.
+ * Dom0 and DomU: register a handler to get notified.
+ * Dom0 only: Correctable errors are reported via VIRQ_MCA
+ * Dom0 and DomU: Uncorrectable errors are reported via nmi handlers
+ */
+#define MC_TYPE_GLOBAL 0
+#define MC_TYPE_BANK 1
+#define MC_TYPE_EXTENDED 2
+#define MC_TYPE_RECOVERY 3
+
+struct mcinfo_common {
+ uint16_t type; /* structure type */
+ uint16_t size; /* size of this struct in bytes */
+};
+
+
+#define MC_FLAG_CORRECTABLE (1 << 0)
+#define MC_FLAG_UNCORRECTABLE (1 << 1)
+#define MC_FLAG_RECOVERABLE (1 << 2)
+#define MC_FLAG_POLLED (1 << 3)
+#define MC_FLAG_RESET (1 << 4)
+#define MC_FLAG_CMCI (1 << 5)
+#define MC_FLAG_MCE (1 << 6)
+/* contains global x86 mc information */
+struct mcinfo_global {
+ struct mcinfo_common common;
+
+ /* running domain at the time in error (most likely the impacted one) */
+ uint16_t mc_domid;
+ uint16_t mc_vcpuid; /* virtual cpu scheduled for mc_domid */
+ uint32_t mc_socketid; /* physical socket of the physical core */
+ uint16_t mc_coreid; /* physical impacted core */
+ uint16_t mc_core_threadid; /* core thread of physical core */
+ uint32_t mc_apicid;
+ uint32_t mc_flags;
+ uint64_t mc_gstatus; /* global status */
+};
+
+/* contains bank local x86 mc information */
+struct mcinfo_bank {
+ struct mcinfo_common common;
+
+ uint16_t mc_bank; /* bank nr */
+ uint16_t mc_domid; /* Usecase 5: domain referenced by mc_addr on dom0
+ * and if mc_addr is valid. Never valid on DomU. */
+ uint64_t mc_status; /* bank status */
+ uint64_t mc_addr; /* bank address, only valid
+ * if addr bit is set in mc_status */
+ uint64_t mc_misc;
+ uint64_t mc_ctrl2;
+ uint64_t mc_tsc;
+};
+
+
+struct mcinfo_msr {
+ uint64_t reg; /* MSR */
+ uint64_t value; /* MSR value */
+};
+
+/* contains mc information from other
+ * or additional mc MSRs */
+struct mcinfo_extended {
+ struct mcinfo_common common;
+
+ /* You can fill up to five registers.
+ * If you need more, then use this structure
+ * multiple times. */
+
+ uint32_t mc_msrs; /* Number of msr with valid values. */
+ /*
+ * Currently Intel extended MSR (32/64) include all gp registers
+ * and E(R)FLAGS, E(R)IP, E(R)MISC, up to 11/19 of them might be
+ * useful at present. So expand this array to 16/32 to leave room.
+ */
+ struct mcinfo_msr mc_msr[sizeof(void *) * 4];
+};
+
+/* Recovery Action flags. Giving recovery result information to DOM0 */
+
+/* Xen takes successful recovery action, the error is recovered */
+#define REC_ACTION_RECOVERED (0x1 << 0)
+/* No action is performed by XEN */
+#define REC_ACTION_NONE (0x1 << 1)
+/* It's possible DOM0 might take action ownership in some case */
+#define REC_ACTION_NEED_RESET (0x1 << 2)
+
+/* Different Recovery Action types, if the action is performed successfully,
+ * REC_ACTION_RECOVERED flag will be returned.
+ */
+
+/* Page Offline Action */
+#define MC_ACTION_PAGE_OFFLINE (0x1 << 0)
+/* CPU offline Action */
+#define MC_ACTION_CPU_OFFLINE (0x1 << 1)
+/* L3 cache disable Action */
+#define MC_ACTION_CACHE_SHRINK (0x1 << 2)
+
+/* Below interface used between XEN/DOM0 for passing XEN's recovery action
+ * information to DOM0.
+ * usage Senario: After offlining broken page, XEN might pass its page offline
+ * recovery action result to DOM0. DOM0 will save the information in
+ * non-volatile memory for further proactive actions, such as offlining the
+ * easy broken page earlier when doing next reboot.
+*/
+struct page_offline_action
+{
+ /* Params for passing the offlined page number to DOM0 */
+ uint64_t mfn;
+ uint64_t status;
+};
+
+struct cpu_offline_action
+{
+ /* Params for passing the identity of the offlined CPU to DOM0 */
+ uint32_t mc_socketid;
+ uint16_t mc_coreid;
+ uint16_t mc_core_threadid;
+};
+
+#define MAX_UNION_SIZE 16
+struct mcinfo_recovery
+{
+ struct mcinfo_common common;
+ uint16_t mc_bank; /* bank nr */
+ uint8_t action_flags;
+ uint8_t action_types;
+ union {
+ struct page_offline_action page_retire;
+ struct cpu_offline_action cpu_offline;
+ uint8_t pad[MAX_UNION_SIZE];
+ } action_info;
+};
+
+
+#define MCINFO_HYPERCALLSIZE 1024
+#define MCINFO_MAXSIZE 768
+
+#define MCINFO_FLAGS_UNCOMPLETE 0x1
+struct mc_info {
+ /* Number of mcinfo_* entries in mi_data */
+ uint32_t mi_nentries;
+ uint32_t flags;
+ uint64_t mi_data[(MCINFO_MAXSIZE - 1) / 8];
+};
+typedef struct mc_info mc_info_t;
+DEFINE_XEN_GUEST_HANDLE(mc_info_t);
+
+#define __MC_MSR_ARRAYSIZE 8
+#define __MC_NMSRS 1
+#define MC_NCAPS 7 /* 7 CPU feature flag words */
+#define MC_CAPS_STD_EDX 0 /* cpuid level 0x00000001 (%edx) */
+#define MC_CAPS_AMD_EDX 1 /* cpuid level 0x80000001 (%edx) */
+#define MC_CAPS_TM 2 /* cpuid level 0x80860001 (TransMeta) */
+#define MC_CAPS_LINUX 3 /* Linux-defined */
+#define MC_CAPS_STD_ECX 4 /* cpuid level 0x00000001 (%ecx) */
+#define MC_CAPS_VIA 5 /* cpuid level 0xc0000001 */
+#define MC_CAPS_AMD_ECX 6 /* cpuid level 0x80000001 (%ecx) */
+
+struct mcinfo_logical_cpu {
+ uint32_t mc_cpunr;
+ uint32_t mc_chipid;
+ uint16_t mc_coreid;
+ uint16_t mc_threadid;
+ uint32_t mc_apicid;
+ uint32_t mc_clusterid;
+ uint32_t mc_ncores;
+ uint32_t mc_ncores_active;
+ uint32_t mc_nthreads;
+ int32_t mc_cpuid_level;
+ uint32_t mc_family;
+ uint32_t mc_vendor;
+ uint32_t mc_model;
+ uint32_t mc_step;
+ char mc_vendorid[16];
+ char mc_brandid[64];
+ uint32_t mc_cpu_caps[MC_NCAPS];
+ uint32_t mc_cache_size;
+ uint32_t mc_cache_alignment;
+ int32_t mc_nmsrvals;
+ struct mcinfo_msr mc_msrvalues[__MC_MSR_ARRAYSIZE];
+};
+typedef struct mcinfo_logical_cpu xen_mc_logical_cpu_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mc_logical_cpu_t);
+
+
+/*
+ * OS's should use these instead of writing their own lookup function
+ * each with its own bugs and drawbacks.
+ * We use macros instead of static inline functions to allow guests
+ * to include this header in assembly files (*.S).
+ */
+/* Prototype:
+ * uint32_t x86_mcinfo_nentries(struct mc_info *mi);
+ */
+#define x86_mcinfo_nentries(_mi) \
+ (_mi)->mi_nentries
+/* Prototype:
+ * struct mcinfo_common *x86_mcinfo_first(struct mc_info *mi);
+ */
+#define x86_mcinfo_first(_mi) \
+ ((struct mcinfo_common *)(_mi)->mi_data)
+/* Prototype:
+ * struct mcinfo_common *x86_mcinfo_next(struct mcinfo_common *mic);
+ */
+#define x86_mcinfo_next(_mic) \
+ ((struct mcinfo_common *)((uint8_t *)(_mic) + (_mic)->size))
+
+/* Prototype:
+ * void x86_mcinfo_lookup(void *ret, struct mc_info *mi, uint16_t type);
+ */
+#define x86_mcinfo_lookup(_ret, _mi, _type) \
+ do { \
+ uint32_t found, i; \
+ struct mcinfo_common *_mic; \
+ \
+ found = 0; \
+ (_ret) = NULL; \
+ if (_mi == NULL) break; \
+ _mic = x86_mcinfo_first(_mi); \
+ for (i = 0; i < x86_mcinfo_nentries(_mi); i++) { \
+ if (_mic->type == (_type)) { \
+ found = 1; \
+ break; \
+ } \
+ _mic = x86_mcinfo_next(_mic); \
+ } \
+ (_ret) = found ? _mic : NULL; \
+ } while (0)
+
+
+/* Usecase 1
+ * Register machine check trap callback handler
+ * (already done via "set_trap_table" hypercall)
+ */
+
+/* Usecase 2
+ * Dom0 registers machine check event callback handler
+ * done by EVTCHNOP_bind_virq
+ */
+
+/* Usecase 3
+ * Fetch machine check data from hypervisor.
+ * Note, this hypercall is special, because both Dom0 and DomU must use this.
+ */
+#define XEN_MC_fetch 1
+struct xen_mc_fetch {
+ /* IN/OUT variables. */
+ uint32_t flags; /* IN: XEN_MC_NONURGENT, XEN_MC_URGENT,
+ XEN_MC_ACK if ack'ing an earlier fetch */
+ /* OUT: XEN_MC_OK, XEN_MC_FETCHFAILED,
+ XEN_MC_NODATA, XEN_MC_NOMATCH */
+ uint32_t _pad0;
+ uint64_t fetch_id; /* OUT: id for ack, IN: id we are ack'ing */
+
+ /* OUT variables. */
+ XEN_GUEST_HANDLE(mc_info_t) data;
+};
+typedef struct xen_mc_fetch xen_mc_fetch_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mc_fetch_t);
+
+
+/* Usecase 4
+ * This tells the hypervisor to notify a DomU about the machine check error
+ */
+#define XEN_MC_notifydomain 2
+struct xen_mc_notifydomain {
+ /* IN variables. */
+ uint16_t mc_domid; /* The unprivileged domain to notify. */
+ uint16_t mc_vcpuid; /* The vcpu in mc_domid to notify.
+ * Usually echo'd value from the fetch hypercall. */
+
+ /* IN/OUT variables. */
+ uint32_t flags;
+
+/* IN: XEN_MC_CORRECTABLE, XEN_MC_TRAP */
+/* OUT: XEN_MC_OK, XEN_MC_CANNOTHANDLE, XEN_MC_NOTDELIVERED, XEN_MC_NOMATCH */
+};
+typedef struct xen_mc_notifydomain xen_mc_notifydomain_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mc_notifydomain_t);
+
+#define XEN_MC_physcpuinfo 3
+struct xen_mc_physcpuinfo {
+ /* IN/OUT */
+ uint32_t ncpus;
+ uint32_t _pad0;
+ /* OUT */
+ XEN_GUEST_HANDLE(xen_mc_logical_cpu_t) info;
+};
+
+#define XEN_MC_msrinject 4
+#define MC_MSRINJ_MAXMSRS 8
+struct xen_mc_msrinject {
+ /* IN */
+ uint32_t mcinj_cpunr; /* target processor id */
+ uint32_t mcinj_flags; /* see MC_MSRINJ_F_* below */
+ uint32_t mcinj_count; /* 0 .. count-1 in array are valid */
+ uint32_t _pad0;
+ struct mcinfo_msr mcinj_msr[MC_MSRINJ_MAXMSRS];
+};
+
+/* Flags for mcinj_flags above; bits 16-31 are reserved */
+#define MC_MSRINJ_F_INTERPOSE 0x1
+
+#define XEN_MC_mceinject 5
+struct xen_mc_mceinject {
+ unsigned int mceinj_cpunr; /* target processor id */
+};
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+#define XEN_MC_inject_v2 6
+#define XEN_MC_INJECT_TYPE_MASK 0x7
+#define XEN_MC_INJECT_TYPE_MCE 0x0
+#define XEN_MC_INJECT_TYPE_CMCI 0x1
+
+#define XEN_MC_INJECT_CPU_BROADCAST 0x8
+
+struct xen_mc_inject_v2 {
+ uint32_t flags;
+ struct xenctl_bitmap cpumap;
+};
+#endif
+
+struct xen_mc {
+ uint32_t cmd;
+ uint32_t interface_version; /* XEN_MCA_INTERFACE_VERSION */
+ union {
+ struct xen_mc_fetch mc_fetch;
+ struct xen_mc_notifydomain mc_notifydomain;
+ struct xen_mc_physcpuinfo mc_physcpuinfo;
+ struct xen_mc_msrinject mc_msrinject;
+ struct xen_mc_mceinject mc_mceinject;
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+ struct xen_mc_inject_v2 mc_inject_v2;
+#endif
+ } u;
+};
+typedef struct xen_mc xen_mc_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mc_t);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __XEN_PUBLIC_ARCH_X86_MCA_H__ */
--- /dev/null
+/******************************************************************************
+ * xen-x86_32.h
+ *
+ * Guest OS interface to x86 32-bit Xen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2004-2007, K A Fraser
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
+#define __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
+
+/*
+ * Hypercall interface:
+ * Input: %ebx, %ecx, %edx, %esi, %edi, %ebp (arguments 1-6)
+ * Output: %eax
+ * Access is via hypercall page (set up by guest loader or via a Xen MSR):
+ * call hypercall_page + hypercall-number * 32
+ * Clobbered: Argument registers (e.g., 2-arg hypercall clobbers %ebx,%ecx)
+ */
+
+/*
+ * These flat segments are in the Xen-private section of every GDT. Since these
+ * are also present in the initial GDT, many OSes will be able to avoid
+ * installing their own GDT.
+ */
+#define FLAT_RING1_CS 0xe019 /* GDT index 259 */
+#define FLAT_RING1_DS 0xe021 /* GDT index 260 */
+#define FLAT_RING1_SS 0xe021 /* GDT index 260 */
+#define FLAT_RING3_CS 0xe02b /* GDT index 261 */
+#define FLAT_RING3_DS 0xe033 /* GDT index 262 */
+#define FLAT_RING3_SS 0xe033 /* GDT index 262 */
+
+#define FLAT_KERNEL_CS FLAT_RING1_CS
+#define FLAT_KERNEL_DS FLAT_RING1_DS
+#define FLAT_KERNEL_SS FLAT_RING1_SS
+#define FLAT_USER_CS FLAT_RING3_CS
+#define FLAT_USER_DS FLAT_RING3_DS
+#define FLAT_USER_SS FLAT_RING3_SS
+
+#define __HYPERVISOR_VIRT_START_PAE 0xF5800000
+#define __MACH2PHYS_VIRT_START_PAE 0xF5800000
+#define __MACH2PHYS_VIRT_END_PAE 0xF6800000
+#define HYPERVISOR_VIRT_START_PAE \
+ mk_unsigned_long(__HYPERVISOR_VIRT_START_PAE)
+#define MACH2PHYS_VIRT_START_PAE \
+ mk_unsigned_long(__MACH2PHYS_VIRT_START_PAE)
+#define MACH2PHYS_VIRT_END_PAE \
+ mk_unsigned_long(__MACH2PHYS_VIRT_END_PAE)
+
+/* Non-PAE bounds are obsolete. */
+#define __HYPERVISOR_VIRT_START_NONPAE 0xFC000000
+#define __MACH2PHYS_VIRT_START_NONPAE 0xFC000000
+#define __MACH2PHYS_VIRT_END_NONPAE 0xFC400000
+#define HYPERVISOR_VIRT_START_NONPAE \
+ mk_unsigned_long(__HYPERVISOR_VIRT_START_NONPAE)
+#define MACH2PHYS_VIRT_START_NONPAE \
+ mk_unsigned_long(__MACH2PHYS_VIRT_START_NONPAE)
+#define MACH2PHYS_VIRT_END_NONPAE \
+ mk_unsigned_long(__MACH2PHYS_VIRT_END_NONPAE)
+
+#define __HYPERVISOR_VIRT_START __HYPERVISOR_VIRT_START_PAE
+#define __MACH2PHYS_VIRT_START __MACH2PHYS_VIRT_START_PAE
+#define __MACH2PHYS_VIRT_END __MACH2PHYS_VIRT_END_PAE
+
+#ifndef HYPERVISOR_VIRT_START
+#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
+#endif
+
+#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START)
+#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END)
+#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>2)
+#ifndef machine_to_phys_mapping
+#define machine_to_phys_mapping ((unsigned long *)MACH2PHYS_VIRT_START)
+#endif
+
+/* 32-/64-bit invariability for control interfaces (domctl/sysctl). */
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+#undef ___DEFINE_XEN_GUEST_HANDLE
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
+ typedef struct { type *p; } \
+ __guest_handle_ ## name; \
+ typedef struct { union { type *p; uint64_aligned_t q; }; } \
+ __guest_handle_64_ ## name
+#undef set_xen_guest_handle_raw
+#define set_xen_guest_handle_raw(hnd, val) \
+ do { if ( sizeof(hnd) == 8 ) *(uint64_t *)&(hnd) = 0; \
+ (hnd).p = val; \
+ } while ( 0 )
+#define uint64_aligned_t uint64_t __attribute__((aligned(8)))
+#define __XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name
+#define XEN_GUEST_HANDLE_64(name) __XEN_GUEST_HANDLE_64(name)
+#endif
+
+#ifndef __ASSEMBLY__
+
+struct cpu_user_regs {
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t esi;
+ uint32_t edi;
+ uint32_t ebp;
+ uint32_t eax;
+ uint16_t error_code; /* private */
+ uint16_t entry_vector; /* private */
+ uint32_t eip;
+ uint16_t cs;
+ uint8_t saved_upcall_mask;
+ uint8_t _pad0;
+ uint32_t eflags; /* eflags.IF == !saved_upcall_mask */
+ uint32_t esp;
+ uint16_t ss, _pad1;
+ uint16_t es, _pad2;
+ uint16_t ds, _pad3;
+ uint16_t fs, _pad4;
+ uint16_t gs, _pad5;
+};
+typedef struct cpu_user_regs cpu_user_regs_t;
+DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
+
+/*
+ * Page-directory addresses above 4GB do not fit into architectural %cr3.
+ * When accessing %cr3, or equivalent field in vcpu_guest_context, guests
+ * must use the following accessor macros to pack/unpack valid MFNs.
+ */
+#define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20))
+#define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20))
+
+struct arch_vcpu_info {
+ unsigned long cr2;
+ unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */
+};
+typedef struct arch_vcpu_info arch_vcpu_info_t;
+
+struct xen_callback {
+ unsigned long cs;
+ unsigned long eip;
+};
+typedef struct xen_callback xen_callback_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * xen-x86_64.h
+ *
+ * Guest OS interface to x86 64-bit Xen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2004-2006, K A Fraser
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
+#define __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
+
+/*
+ * Hypercall interface:
+ * Input: %rdi, %rsi, %rdx, %r10, %r8, %r9 (arguments 1-6)
+ * Output: %rax
+ * Access is via hypercall page (set up by guest loader or via a Xen MSR):
+ * call hypercall_page + hypercall-number * 32
+ * Clobbered: argument registers (e.g., 2-arg hypercall clobbers %rdi,%rsi)
+ */
+
+/*
+ * 64-bit segment selectors
+ * These flat segments are in the Xen-private section of every GDT. Since these
+ * are also present in the initial GDT, many OSes will be able to avoid
+ * installing their own GDT.
+ */
+
+#define FLAT_RING3_CS32 0xe023 /* GDT index 260 */
+#define FLAT_RING3_CS64 0xe033 /* GDT index 261 */
+#define FLAT_RING3_DS32 0xe02b /* GDT index 262 */
+#define FLAT_RING3_DS64 0x0000 /* NULL selector */
+#define FLAT_RING3_SS32 0xe02b /* GDT index 262 */
+#define FLAT_RING3_SS64 0xe02b /* GDT index 262 */
+
+#define FLAT_KERNEL_DS64 FLAT_RING3_DS64
+#define FLAT_KERNEL_DS32 FLAT_RING3_DS32
+#define FLAT_KERNEL_DS FLAT_KERNEL_DS64
+#define FLAT_KERNEL_CS64 FLAT_RING3_CS64
+#define FLAT_KERNEL_CS32 FLAT_RING3_CS32
+#define FLAT_KERNEL_CS FLAT_KERNEL_CS64
+#define FLAT_KERNEL_SS64 FLAT_RING3_SS64
+#define FLAT_KERNEL_SS32 FLAT_RING3_SS32
+#define FLAT_KERNEL_SS FLAT_KERNEL_SS64
+
+#define FLAT_USER_DS64 FLAT_RING3_DS64
+#define FLAT_USER_DS32 FLAT_RING3_DS32
+#define FLAT_USER_DS FLAT_USER_DS64
+#define FLAT_USER_CS64 FLAT_RING3_CS64
+#define FLAT_USER_CS32 FLAT_RING3_CS32
+#define FLAT_USER_CS FLAT_USER_CS64
+#define FLAT_USER_SS64 FLAT_RING3_SS64
+#define FLAT_USER_SS32 FLAT_RING3_SS32
+#define FLAT_USER_SS FLAT_USER_SS64
+
+#define __HYPERVISOR_VIRT_START 0xFFFF800000000000
+#define __HYPERVISOR_VIRT_END 0xFFFF880000000000
+#define __MACH2PHYS_VIRT_START 0xFFFF800000000000
+#define __MACH2PHYS_VIRT_END 0xFFFF804000000000
+
+#ifndef HYPERVISOR_VIRT_START
+#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
+#define HYPERVISOR_VIRT_END mk_unsigned_long(__HYPERVISOR_VIRT_END)
+#endif
+
+#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START)
+#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END)
+#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3)
+#ifndef machine_to_phys_mapping
+#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
+#endif
+
+/*
+ * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base)
+ * @which == SEGBASE_* ; @base == 64-bit base address
+ * Returns 0 on success.
+ */
+#define SEGBASE_FS 0
+#define SEGBASE_GS_USER 1
+#define SEGBASE_GS_KERNEL 2
+#define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */
+
+/*
+ * int HYPERVISOR_iret(void)
+ * All arguments are on the kernel stack, in the following format.
+ * Never returns if successful. Current kernel context is lost.
+ * The saved CS is mapped as follows:
+ * RING0 -> RING3 kernel mode.
+ * RING1 -> RING3 kernel mode.
+ * RING2 -> RING3 kernel mode.
+ * RING3 -> RING3 user mode.
+ * However RING0 indicates that the guest kernel should return to iteself
+ * directly with
+ * orb $3,1*8(%rsp)
+ * iretq
+ * If flags contains VGCF_in_syscall:
+ * Restore RAX, RIP, RFLAGS, RSP.
+ * Discard R11, RCX, CS, SS.
+ * Otherwise:
+ * Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP.
+ * All other registers are saved on hypercall entry and restored to user.
+ */
+/* Guest exited in SYSCALL context? Return to guest with SYSRET? */
+#define _VGCF_in_syscall 8
+#define VGCF_in_syscall (1<<_VGCF_in_syscall)
+#define VGCF_IN_SYSCALL VGCF_in_syscall
+
+#ifndef __ASSEMBLY__
+
+struct iret_context {
+ /* Top of stack (%rsp at point of hypercall). */
+ uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
+ /* Bottom of iret stack frame. */
+};
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+/* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */
+#define __DECL_REG(name) union { \
+ uint64_t r ## name, e ## name; \
+ uint32_t _e ## name; \
+}
+#else
+/* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */
+#define __DECL_REG(name) uint64_t r ## name
+#endif
+
+struct cpu_user_regs {
+ uint64_t r15;
+ uint64_t r14;
+ uint64_t r13;
+ uint64_t r12;
+ __DECL_REG(bp);
+ __DECL_REG(bx);
+ uint64_t r11;
+ uint64_t r10;
+ uint64_t r9;
+ uint64_t r8;
+ __DECL_REG(ax);
+ __DECL_REG(cx);
+ __DECL_REG(dx);
+ __DECL_REG(si);
+ __DECL_REG(di);
+ uint32_t error_code; /* private */
+ uint32_t entry_vector; /* private */
+ __DECL_REG(ip);
+ uint16_t cs, _pad0[1];
+ uint8_t saved_upcall_mask;
+ uint8_t _pad1[3];
+ __DECL_REG(flags); /* rflags.IF == !saved_upcall_mask */
+ __DECL_REG(sp);
+ uint16_t ss, _pad2[3];
+ uint16_t es, _pad3[3];
+ uint16_t ds, _pad4[3];
+ uint16_t fs, _pad5[3]; /* Non-zero => takes precedence over fs_base. */
+ uint16_t gs, _pad6[3]; /* Non-zero => takes precedence over gs_base_usr. */
+};
+typedef struct cpu_user_regs cpu_user_regs_t;
+DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
+
+#undef __DECL_REG
+
+#define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12)
+#define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12)
+
+struct arch_vcpu_info {
+ unsigned long cr2;
+ unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
+};
+typedef struct arch_vcpu_info arch_vcpu_info_t;
+
+typedef unsigned long xen_callback_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * arch-x86/xen.h
+ *
+ * Guest OS interface to x86 Xen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2004-2006, K A Fraser
+ */
+
+#include "../xen.h"
+
+#ifndef __XEN_PUBLIC_ARCH_X86_XEN_H__
+#define __XEN_PUBLIC_ARCH_X86_XEN_H__
+
+/* Structural guest handles introduced in 0x00030201. */
+#if __XEN_INTERFACE_VERSION__ >= 0x00030201
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
+ typedef struct { type *p; } __guest_handle_ ## name
+#else
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
+ typedef type * __guest_handle_ ## name
+#endif
+
+/*
+ * XEN_GUEST_HANDLE represents a guest pointer, when passed as a field
+ * in a struct in memory.
+ * XEN_GUEST_HANDLE_PARAM represent a guest pointer, when passed as an
+ * hypercall argument.
+ * XEN_GUEST_HANDLE_PARAM and XEN_GUEST_HANDLE are the same on X86 but
+ * they might not be on other architectures.
+ */
+#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
+ ___DEFINE_XEN_GUEST_HANDLE(name, type); \
+ ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
+#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
+#define __XEN_GUEST_HANDLE(name) __guest_handle_ ## name
+#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name)
+#define XEN_GUEST_HANDLE_PARAM(name) XEN_GUEST_HANDLE(name)
+#define set_xen_guest_handle_raw(hnd, val) do { (hnd).p = val; } while (0)
+#ifdef __XEN_TOOLS__
+#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0)
+#endif
+#define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val)
+
+#if defined(__i386__)
+#include "xen-x86_32.h"
+#elif defined(__x86_64__)
+#include "xen-x86_64.h"
+#endif
+
+#ifndef __ASSEMBLY__
+typedef unsigned long xen_pfn_t;
+#define PRI_xen_pfn "lx"
+#endif
+
+#define XEN_HAVE_PV_GUEST_ENTRY 1
+
+#define XEN_HAVE_PV_UPCALL_MASK 1
+
+/*
+ * `incontents 200 segdesc Segment Descriptor Tables
+ */
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_set_gdt(const xen_pfn_t frames[], unsigned int entries);
+ * `
+ */
+/*
+ * A number of GDT entries are reserved by Xen. These are not situated at the
+ * start of the GDT because some stupid OSes export hard-coded selector values
+ * in their ABI. These hard-coded values are always near the start of the GDT,
+ * so Xen places itself out of the way, at the far end of the GDT.
+ *
+ * NB The LDT is set using the MMUEXT_SET_LDT op of HYPERVISOR_mmuext_op
+ */
+#define FIRST_RESERVED_GDT_PAGE 14
+#define FIRST_RESERVED_GDT_BYTE (FIRST_RESERVED_GDT_PAGE * 4096)
+#define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8)
+
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_update_descriptor(u64 pa, u64 desc);
+ * `
+ * ` @pa The machine physical address of the descriptor to
+ * ` update. Must be either a descriptor page or writable.
+ * ` @desc The descriptor value to update, in the same format as a
+ * ` native descriptor table entry.
+ */
+
+/* Maximum number of virtual CPUs in legacy multi-processor guests. */
+#define XEN_LEGACY_MAX_VCPUS 32
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long xen_ulong_t;
+#define PRI_xen_ulong "lx"
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp);
+ * `
+ * Sets the stack segment and pointer for the current vcpu.
+ */
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_set_trap_table(const struct trap_info traps[]);
+ * `
+ */
+/*
+ * Send an array of these to HYPERVISOR_set_trap_table().
+ * Terminate the array with a sentinel entry, with traps[].address==0.
+ * The privilege level specifies which modes may enter a trap via a software
+ * interrupt. On x86/64, since rings 1 and 2 are unavailable, we allocate
+ * privilege levels as follows:
+ * Level == 0: Noone may enter
+ * Level == 1: Kernel may enter
+ * Level == 2: Kernel may enter
+ * Level == 3: Everyone may enter
+ */
+#define TI_GET_DPL(_ti) ((_ti)->flags & 3)
+#define TI_GET_IF(_ti) ((_ti)->flags & 4)
+#define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl))
+#define TI_SET_IF(_ti,_if) ((_ti)->flags |= ((!!(_if))<<2))
+struct trap_info {
+ uint8_t vector; /* exception vector */
+ uint8_t flags; /* 0-3: privilege level; 4: clear event enable? */
+ uint16_t cs; /* code selector */
+ unsigned long address; /* code offset */
+};
+typedef struct trap_info trap_info_t;
+DEFINE_XEN_GUEST_HANDLE(trap_info_t);
+
+typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
+
+/*
+ * The following is all CPU context. Note that the fpu_ctxt block is filled
+ * in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
+ *
+ * Also note that when calling DOMCTL_setvcpucontext and VCPU_initialise
+ * for HVM and PVH guests, not all information in this structure is updated:
+ *
+ * - For HVM guests, the structures read include: fpu_ctxt (if
+ * VGCT_I387_VALID is set), flags, user_regs, debugreg[*]
+ *
+ * - PVH guests are the same as HVM guests, but additionally use ctrlreg[3] to
+ * set cr3. All other fields not used should be set to 0.
+ */
+struct vcpu_guest_context {
+ /* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
+ struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */
+#define VGCF_I387_VALID (1<<0)
+#define VGCF_IN_KERNEL (1<<2)
+#define _VGCF_i387_valid 0
+#define VGCF_i387_valid (1<<_VGCF_i387_valid)
+#define _VGCF_in_kernel 2
+#define VGCF_in_kernel (1<<_VGCF_in_kernel)
+#define _VGCF_failsafe_disables_events 3
+#define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events)
+#define _VGCF_syscall_disables_events 4
+#define VGCF_syscall_disables_events (1<<_VGCF_syscall_disables_events)
+#define _VGCF_online 5
+#define VGCF_online (1<<_VGCF_online)
+ unsigned long flags; /* VGCF_* flags */
+ struct cpu_user_regs user_regs; /* User-level CPU registers */
+ struct trap_info trap_ctxt[256]; /* Virtual IDT */
+ unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */
+ unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
+ unsigned long kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */
+ /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */
+ unsigned long ctrlreg[8]; /* CR0-CR7 (control registers) */
+ unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */
+#ifdef __i386__
+ unsigned long event_callback_cs; /* CS:EIP of event callback */
+ unsigned long event_callback_eip;
+ unsigned long failsafe_callback_cs; /* CS:EIP of failsafe callback */
+ unsigned long failsafe_callback_eip;
+#else
+ unsigned long event_callback_eip;
+ unsigned long failsafe_callback_eip;
+#ifdef __XEN__
+ union {
+ unsigned long syscall_callback_eip;
+ struct {
+ unsigned int event_callback_cs; /* compat CS of event cb */
+ unsigned int failsafe_callback_cs; /* compat CS of failsafe cb */
+ };
+ };
+#else
+ unsigned long syscall_callback_eip;
+#endif
+#endif
+ unsigned long vm_assist; /* VMASST_TYPE_* bitmap */
+#ifdef __x86_64__
+ /* Segment base addresses. */
+ uint64_t fs_base;
+ uint64_t gs_base_kernel;
+ uint64_t gs_base_user;
+#endif
+};
+typedef struct vcpu_guest_context vcpu_guest_context_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
+
+struct arch_shared_info {
+ /*
+ * Number of valid entries in the p2m table(s) anchored at
+ * pfn_to_mfn_frame_list_list and/or p2m_vaddr.
+ */
+ unsigned long max_pfn;
+ /*
+ * Frame containing list of mfns containing list of mfns containing p2m.
+ * A value of 0 indicates it has not yet been set up, ~0 indicates it has
+ * been set to invalid e.g. due to the p2m being too large for the 3-level
+ * p2m tree. In this case the linear mapper p2m list anchored at p2m_vaddr
+ * is to be used.
+ */
+ xen_pfn_t pfn_to_mfn_frame_list_list;
+ unsigned long nmi_reason;
+ /*
+ * Following three fields are valid if p2m_cr3 contains a value different
+ * from 0.
+ * p2m_cr3 is the root of the address space where p2m_vaddr is valid.
+ * p2m_cr3 is in the same format as a cr3 value in the vcpu register state
+ * and holds the folded machine frame number (via xen_pfn_to_cr3) of a
+ * L3 or L4 page table.
+ * p2m_vaddr holds the virtual address of the linear p2m list. All entries
+ * in the range [0...max_pfn[ are accessible via this pointer.
+ * p2m_generation will be incremented by the guest before and after each
+ * change of the mappings of the p2m list. p2m_generation starts at 0 and
+ * a value with the least significant bit set indicates that a mapping
+ * update is in progress. This allows guest external software (e.g. in Dom0)
+ * to verify that read mappings are consistent and whether they have changed
+ * since the last check.
+ * Modifying a p2m element in the linear p2m list is allowed via an atomic
+ * write only.
+ */
+ unsigned long p2m_cr3; /* cr3 value of the p2m address space */
+ unsigned long p2m_vaddr; /* virtual address of the p2m list */
+ unsigned long p2m_generation; /* generation count of p2m mapping */
+};
+typedef struct arch_shared_info arch_shared_info_t;
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_fpu_taskswitch(int set);
+ * `
+ * Sets (if set!=0) or clears (if set==0) CR0.TS.
+ */
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_set_debugreg(int regno, unsigned long value);
+ *
+ * ` unsigned long
+ * ` HYPERVISOR_get_debugreg(int regno);
+ * For 0<=reg<=7, returns the debug register value.
+ * For other values of reg, returns ((unsigned long)-EINVAL).
+ * (Unfortunately, this interface is defective.)
+ */
+
+/*
+ * Prefix forces emulation of some non-trapping instructions.
+ * Currently only CPUID.
+ */
+#ifdef __ASSEMBLY__
+#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ;
+#define XEN_CPUID XEN_EMULATE_PREFIX cpuid
+#else
+#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; "
+#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid"
+#endif
+
+#endif /* __XEN_PUBLIC_ARCH_X86_XEN_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * arch-x86_32.h
+ *
+ * Guest OS interface to x86 32-bit Xen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2004-2006, K A Fraser
+ */
+
+#include "arch-x86/xen.h"
--- /dev/null
+/******************************************************************************
+ * arch-x86_64.h
+ *
+ * Guest OS interface to x86 64-bit Xen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2004-2006, K A Fraser
+ */
+
+#include "arch-x86/xen.h"
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_set_callbacks(unsigned long event_selector,
+ * ` unsigned long event_address,
+ * ` unsigned long failsafe_selector,
+ * ` unsigned long failsafe_address);
+ * `
+ * Register for callbacks on events. When an event (from an event
+ * channel) occurs, event_address is used as the value of eip.
+ *
+ * A similar callback occurs if the segment selectors are invalid.
+ * failsafe_address is used as the value of eip.
+ *
+ * On x86_64, event_selector and failsafe_selector are ignored (???).
+ */
--- /dev/null
+/******************************************************************************
+ * callback.h
+ *
+ * Register guest OS callbacks with Xen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2006, Ian Campbell
+ */
+
+#ifndef __XEN_PUBLIC_CALLBACK_H__
+#define __XEN_PUBLIC_CALLBACK_H__
+
+#include "xen.h"
+
+/*
+ * Prototype for this hypercall is:
+ * long callback_op(int cmd, void *extra_args)
+ * @cmd == CALLBACKOP_??? (callback operation).
+ * @extra_args == Operation-specific extra arguments (NULL if none).
+ */
+
+/* x86: Callback for event delivery. */
+#define CALLBACKTYPE_event 0
+
+/* x86: Failsafe callback when guest state cannot be restored by Xen. */
+#define CALLBACKTYPE_failsafe 1
+
+/* x86/64 hypervisor: Syscall by 64-bit guest app ('64-on-64-on-64'). */
+#define CALLBACKTYPE_syscall 2
+
+/*
+ * x86/32 hypervisor: Only available on x86/32 when supervisor_mode_kernel
+ * feature is enabled. Do not use this callback type in new code.
+ */
+#define CALLBACKTYPE_sysenter_deprecated 3
+
+/* x86: Callback for NMI delivery. */
+#define CALLBACKTYPE_nmi 4
+
+/*
+ * x86: sysenter is only available as follows:
+ * - 32-bit hypervisor: with the supervisor_mode_kernel feature enabled
+ * - 64-bit hypervisor: 32-bit guest applications on Intel CPUs
+ * ('32-on-32-on-64', '32-on-64-on-64')
+ * [nb. also 64-bit guest applications on Intel CPUs
+ * ('64-on-64-on-64'), but syscall is preferred]
+ */
+#define CALLBACKTYPE_sysenter 5
+
+/*
+ * x86/64 hypervisor: Syscall by 32-bit guest app on AMD CPUs
+ * ('32-on-32-on-64', '32-on-64-on-64')
+ */
+#define CALLBACKTYPE_syscall32 7
+
+/*
+ * Disable event deliver during callback? This flag is ignored for event and
+ * NMI callbacks: event delivery is unconditionally disabled.
+ */
+#define _CALLBACKF_mask_events 0
+#define CALLBACKF_mask_events (1U << _CALLBACKF_mask_events)
+
+/*
+ * Register a callback.
+ */
+#define CALLBACKOP_register 0
+struct callback_register {
+ uint16_t type;
+ uint16_t flags;
+ xen_callback_t address;
+};
+typedef struct callback_register callback_register_t;
+DEFINE_XEN_GUEST_HANDLE(callback_register_t);
+
+/*
+ * Unregister a callback.
+ *
+ * Not all callbacks can be unregistered. -EINVAL will be returned if
+ * you attempt to unregister such a callback.
+ */
+#define CALLBACKOP_unregister 1
+struct callback_unregister {
+ uint16_t type;
+ uint16_t _unused;
+};
+typedef struct callback_unregister callback_unregister_t;
+DEFINE_XEN_GUEST_HANDLE(callback_unregister_t);
+
+#if __XEN_INTERFACE_VERSION__ < 0x00030207
+#undef CALLBACKTYPE_sysenter
+#define CALLBACKTYPE_sysenter CALLBACKTYPE_sysenter_deprecated
+#endif
+
+#endif /* __XEN_PUBLIC_CALLBACK_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * dom0_ops.h
+ *
+ * Process command requests from domain-0 guest OS.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2002-2003, B Dragovic
+ * Copyright (c) 2002-2006, K Fraser
+ */
+
+#ifndef __XEN_PUBLIC_DOM0_OPS_H__
+#define __XEN_PUBLIC_DOM0_OPS_H__
+
+#include "xen.h"
+#include "platform.h"
+
+#if __XEN_INTERFACE_VERSION__ >= 0x00030204
+#error "dom0_ops.h is a compatibility interface only"
+#endif
+
+#define DOM0_INTERFACE_VERSION XENPF_INTERFACE_VERSION
+
+#define DOM0_SETTIME XENPF_settime
+#define dom0_settime xenpf_settime
+#define dom0_settime_t xenpf_settime_t
+
+#define DOM0_ADD_MEMTYPE XENPF_add_memtype
+#define dom0_add_memtype xenpf_add_memtype
+#define dom0_add_memtype_t xenpf_add_memtype_t
+
+#define DOM0_DEL_MEMTYPE XENPF_del_memtype
+#define dom0_del_memtype xenpf_del_memtype
+#define dom0_del_memtype_t xenpf_del_memtype_t
+
+#define DOM0_READ_MEMTYPE XENPF_read_memtype
+#define dom0_read_memtype xenpf_read_memtype
+#define dom0_read_memtype_t xenpf_read_memtype_t
+
+#define DOM0_MICROCODE XENPF_microcode_update
+#define dom0_microcode xenpf_microcode_update
+#define dom0_microcode_t xenpf_microcode_update_t
+
+#define DOM0_PLATFORM_QUIRK XENPF_platform_quirk
+#define dom0_platform_quirk xenpf_platform_quirk
+#define dom0_platform_quirk_t xenpf_platform_quirk_t
+
+typedef uint64_t cpumap_t;
+
+/* Unsupported legacy operation -- defined for API compatibility. */
+#define DOM0_MSR 15
+struct dom0_msr {
+ /* IN variables. */
+ uint32_t write;
+ cpumap_t cpu_mask;
+ uint32_t msr;
+ uint32_t in1;
+ uint32_t in2;
+ /* OUT variables. */
+ uint32_t out1;
+ uint32_t out2;
+};
+typedef struct dom0_msr dom0_msr_t;
+DEFINE_XEN_GUEST_HANDLE(dom0_msr_t);
+
+/* Unsupported legacy operation -- defined for API compatibility. */
+#define DOM0_PHYSICAL_MEMORY_MAP 40
+struct dom0_memory_map_entry {
+ uint64_t start, end;
+ uint32_t flags; /* reserved */
+ uint8_t is_ram;
+};
+typedef struct dom0_memory_map_entry dom0_memory_map_entry_t;
+DEFINE_XEN_GUEST_HANDLE(dom0_memory_map_entry_t);
+
+struct dom0_op {
+ uint32_t cmd;
+ uint32_t interface_version; /* DOM0_INTERFACE_VERSION */
+ union {
+ struct dom0_msr msr;
+ struct dom0_settime settime;
+ struct dom0_add_memtype add_memtype;
+ struct dom0_del_memtype del_memtype;
+ struct dom0_read_memtype read_memtype;
+ struct dom0_microcode microcode;
+ struct dom0_platform_quirk platform_quirk;
+ struct dom0_memory_map_entry physical_memory_map;
+ uint8_t pad[128];
+ } u;
+};
+typedef struct dom0_op dom0_op_t;
+DEFINE_XEN_GUEST_HANDLE(dom0_op_t);
+
+#endif /* __XEN_PUBLIC_DOM0_OPS_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * domctl.h
+ *
+ * Domain management operations. For use by node control stack.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2002-2003, B Dragovic
+ * Copyright (c) 2002-2006, K Fraser
+ */
+
+#ifndef __XEN_PUBLIC_DOMCTL_H__
+#define __XEN_PUBLIC_DOMCTL_H__
+
+#if !defined(__XEN__) && !defined(__XEN_TOOLS__)
+#error "domctl operations are intended for use by node control tools only"
+#endif
+
+#include "xen.h"
+#include "grant_table.h"
+#include "hvm/save.h"
+#include "memory.h"
+
+#define XEN_DOMCTL_INTERFACE_VERSION 0x0000000a
+
+/*
+ * NB. xen_domctl.domain is an IN/OUT parameter for this operation.
+ * If it is specified as zero, an id is auto-allocated and returned.
+ */
+/* XEN_DOMCTL_createdomain */
+struct xen_domctl_createdomain {
+ /* IN parameters */
+ uint32_t ssidref;
+ xen_domain_handle_t handle;
+ /* Is this an HVM guest (as opposed to a PVH or PV guest)? */
+#define _XEN_DOMCTL_CDF_hvm_guest 0
+#define XEN_DOMCTL_CDF_hvm_guest (1U<<_XEN_DOMCTL_CDF_hvm_guest)
+ /* Use hardware-assisted paging if available? */
+#define _XEN_DOMCTL_CDF_hap 1
+#define XEN_DOMCTL_CDF_hap (1U<<_XEN_DOMCTL_CDF_hap)
+ /* Should domain memory integrity be verifed by tboot during Sx? */
+#define _XEN_DOMCTL_CDF_s3_integrity 2
+#define XEN_DOMCTL_CDF_s3_integrity (1U<<_XEN_DOMCTL_CDF_s3_integrity)
+ /* Disable out-of-sync shadow page tables? */
+#define _XEN_DOMCTL_CDF_oos_off 3
+#define XEN_DOMCTL_CDF_oos_off (1U<<_XEN_DOMCTL_CDF_oos_off)
+ /* Is this a PVH guest (as opposed to an HVM or PV guest)? */
+#define _XEN_DOMCTL_CDF_pvh_guest 4
+#define XEN_DOMCTL_CDF_pvh_guest (1U<<_XEN_DOMCTL_CDF_pvh_guest)
+ uint32_t flags;
+};
+typedef struct xen_domctl_createdomain xen_domctl_createdomain_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_createdomain_t);
+
+#if defined(__arm__) || defined(__aarch64__)
+#define XEN_DOMCTL_CONFIG_GIC_DEFAULT 0
+#define XEN_DOMCTL_CONFIG_GIC_V2 1
+#define XEN_DOMCTL_CONFIG_GIC_V3 2
+/* XEN_DOMCTL_configure_domain */
+struct xen_domctl_arm_configuredomain {
+ /* IN/OUT parameters */
+ uint8_t gic_version;
+};
+typedef struct xen_domctl_arm_configuredomain xen_domctl_arm_configuredomain_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_arm_configuredomain_t);
+#endif
+
+/* XEN_DOMCTL_getdomaininfo */
+struct xen_domctl_getdomaininfo {
+ /* OUT variables. */
+ domid_t domain; /* Also echoed in domctl.domain */
+ /* Domain is scheduled to die. */
+#define _XEN_DOMINF_dying 0
+#define XEN_DOMINF_dying (1U<<_XEN_DOMINF_dying)
+ /* Domain is an HVM guest (as opposed to a PV guest). */
+#define _XEN_DOMINF_hvm_guest 1
+#define XEN_DOMINF_hvm_guest (1U<<_XEN_DOMINF_hvm_guest)
+ /* The guest OS has shut down. */
+#define _XEN_DOMINF_shutdown 2
+#define XEN_DOMINF_shutdown (1U<<_XEN_DOMINF_shutdown)
+ /* Currently paused by control software. */
+#define _XEN_DOMINF_paused 3
+#define XEN_DOMINF_paused (1U<<_XEN_DOMINF_paused)
+ /* Currently blocked pending an event. */
+#define _XEN_DOMINF_blocked 4
+#define XEN_DOMINF_blocked (1U<<_XEN_DOMINF_blocked)
+ /* Domain is currently running. */
+#define _XEN_DOMINF_running 5
+#define XEN_DOMINF_running (1U<<_XEN_DOMINF_running)
+ /* Being debugged. */
+#define _XEN_DOMINF_debugged 6
+#define XEN_DOMINF_debugged (1U<<_XEN_DOMINF_debugged)
+/* domain is PVH */
+#define _XEN_DOMINF_pvh_guest 7
+#define XEN_DOMINF_pvh_guest (1U<<_XEN_DOMINF_pvh_guest)
+ /* XEN_DOMINF_shutdown guest-supplied code. */
+#define XEN_DOMINF_shutdownmask 255
+#define XEN_DOMINF_shutdownshift 16
+ uint32_t flags; /* XEN_DOMINF_* */
+ uint64_aligned_t tot_pages;
+ uint64_aligned_t max_pages;
+ uint64_aligned_t outstanding_pages;
+ uint64_aligned_t shr_pages;
+ uint64_aligned_t paged_pages;
+ uint64_aligned_t shared_info_frame; /* GMFN of shared_info struct */
+ uint64_aligned_t cpu_time;
+ uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
+#define XEN_INVALID_MAX_VCPU_ID (~0U) /* Domain has no vcpus? */
+ uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
+ uint32_t ssidref;
+ xen_domain_handle_t handle;
+ uint32_t cpupool;
+};
+typedef struct xen_domctl_getdomaininfo xen_domctl_getdomaininfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getdomaininfo_t);
+
+
+/* XEN_DOMCTL_getmemlist */
+struct xen_domctl_getmemlist {
+ /* IN variables. */
+ /* Max entries to write to output buffer. */
+ uint64_aligned_t max_pfns;
+ /* Start index in guest's page list. */
+ uint64_aligned_t start_pfn;
+ XEN_GUEST_HANDLE_64(uint64) buffer;
+ /* OUT variables. */
+ uint64_aligned_t num_pfns;
+};
+typedef struct xen_domctl_getmemlist xen_domctl_getmemlist_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getmemlist_t);
+
+
+/* XEN_DOMCTL_getpageframeinfo */
+
+#define XEN_DOMCTL_PFINFO_LTAB_SHIFT 28
+#define XEN_DOMCTL_PFINFO_NOTAB (0x0U<<28)
+#define XEN_DOMCTL_PFINFO_L1TAB (0x1U<<28)
+#define XEN_DOMCTL_PFINFO_L2TAB (0x2U<<28)
+#define XEN_DOMCTL_PFINFO_L3TAB (0x3U<<28)
+#define XEN_DOMCTL_PFINFO_L4TAB (0x4U<<28)
+#define XEN_DOMCTL_PFINFO_LTABTYPE_MASK (0x7U<<28)
+#define XEN_DOMCTL_PFINFO_LPINTAB (0x1U<<31)
+#define XEN_DOMCTL_PFINFO_XTAB (0xfU<<28) /* invalid page */
+#define XEN_DOMCTL_PFINFO_XALLOC (0xeU<<28) /* allocate-only page */
+#define XEN_DOMCTL_PFINFO_BROKEN (0xdU<<28) /* broken page */
+#define XEN_DOMCTL_PFINFO_LTAB_MASK (0xfU<<28)
+
+struct xen_domctl_getpageframeinfo {
+ /* IN variables. */
+ uint64_aligned_t gmfn; /* GMFN to query */
+ /* OUT variables. */
+ /* Is the page PINNED to a type? */
+ uint32_t type; /* see above type defs */
+};
+typedef struct xen_domctl_getpageframeinfo xen_domctl_getpageframeinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo_t);
+
+
+/* XEN_DOMCTL_getpageframeinfo2 */
+struct xen_domctl_getpageframeinfo2 {
+ /* IN variables. */
+ uint64_aligned_t num;
+ /* IN/OUT variables. */
+ XEN_GUEST_HANDLE_64(uint32) array;
+};
+typedef struct xen_domctl_getpageframeinfo2 xen_domctl_getpageframeinfo2_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo2_t);
+
+/* XEN_DOMCTL_getpageframeinfo3 */
+struct xen_domctl_getpageframeinfo3 {
+ /* IN variables. */
+ uint64_aligned_t num;
+ /* IN/OUT variables. */
+ XEN_GUEST_HANDLE_64(xen_pfn_t) array;
+};
+
+
+/*
+ * Control shadow pagetables operation
+ */
+/* XEN_DOMCTL_shadow_op */
+
+/* Disable shadow mode. */
+#define XEN_DOMCTL_SHADOW_OP_OFF 0
+
+/* Enable shadow mode (mode contains ORed XEN_DOMCTL_SHADOW_ENABLE_* flags). */
+#define XEN_DOMCTL_SHADOW_OP_ENABLE 32
+
+/* Log-dirty bitmap operations. */
+ /* Return the bitmap and clean internal copy for next round. */
+#define XEN_DOMCTL_SHADOW_OP_CLEAN 11
+ /* Return the bitmap but do not modify internal copy. */
+#define XEN_DOMCTL_SHADOW_OP_PEEK 12
+
+/* Memory allocation accessors. */
+#define XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION 30
+#define XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION 31
+
+/* Legacy enable operations. */
+ /* Equiv. to ENABLE with no mode flags. */
+#define XEN_DOMCTL_SHADOW_OP_ENABLE_TEST 1
+ /* Equiv. to ENABLE with mode flag ENABLE_LOG_DIRTY. */
+#define XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY 2
+ /* Equiv. to ENABLE with mode flags ENABLE_REFCOUNT and ENABLE_TRANSLATE. */
+#define XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE 3
+
+/* Mode flags for XEN_DOMCTL_SHADOW_OP_ENABLE. */
+ /*
+ * Shadow pagetables are refcounted: guest does not use explicit mmu
+ * operations nor write-protect its pagetables.
+ */
+#define XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT (1 << 1)
+ /*
+ * Log pages in a bitmap as they are dirtied.
+ * Used for live relocation to determine which pages must be re-sent.
+ */
+#define XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY (1 << 2)
+ /*
+ * Automatically translate GPFNs into MFNs.
+ */
+#define XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE (1 << 3)
+ /*
+ * Xen does not steal virtual address space from the guest.
+ * Requires HVM support.
+ */
+#define XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL (1 << 4)
+
+struct xen_domctl_shadow_op_stats {
+ uint32_t fault_count;
+ uint32_t dirty_count;
+};
+typedef struct xen_domctl_shadow_op_stats xen_domctl_shadow_op_stats_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_stats_t);
+
+struct xen_domctl_shadow_op {
+ /* IN variables. */
+ uint32_t op; /* XEN_DOMCTL_SHADOW_OP_* */
+
+ /* OP_ENABLE */
+ uint32_t mode; /* XEN_DOMCTL_SHADOW_ENABLE_* */
+
+ /* OP_GET_ALLOCATION / OP_SET_ALLOCATION */
+ uint32_t mb; /* Shadow memory allocation in MB */
+
+ /* OP_PEEK / OP_CLEAN */
+ XEN_GUEST_HANDLE_64(uint8) dirty_bitmap;
+ uint64_aligned_t pages; /* Size of buffer. Updated with actual size. */
+ struct xen_domctl_shadow_op_stats stats;
+};
+typedef struct xen_domctl_shadow_op xen_domctl_shadow_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_t);
+
+
+/* XEN_DOMCTL_max_mem */
+struct xen_domctl_max_mem {
+ /* IN variables. */
+ uint64_aligned_t max_memkb;
+};
+typedef struct xen_domctl_max_mem xen_domctl_max_mem_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_mem_t);
+
+
+/* XEN_DOMCTL_setvcpucontext */
+/* XEN_DOMCTL_getvcpucontext */
+struct xen_domctl_vcpucontext {
+ uint32_t vcpu; /* IN */
+ XEN_GUEST_HANDLE_64(vcpu_guest_context_t) ctxt; /* IN/OUT */
+};
+typedef struct xen_domctl_vcpucontext xen_domctl_vcpucontext_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpucontext_t);
+
+
+/* XEN_DOMCTL_getvcpuinfo */
+struct xen_domctl_getvcpuinfo {
+ /* IN variables. */
+ uint32_t vcpu;
+ /* OUT variables. */
+ uint8_t online; /* currently online (not hotplugged)? */
+ uint8_t blocked; /* blocked waiting for an event? */
+ uint8_t running; /* currently scheduled on its CPU? */
+ uint64_aligned_t cpu_time; /* total cpu time consumed (ns) */
+ uint32_t cpu; /* current mapping */
+};
+typedef struct xen_domctl_getvcpuinfo xen_domctl_getvcpuinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getvcpuinfo_t);
+
+
+/* Get/set the NUMA node(s) with which the guest has affinity with. */
+/* XEN_DOMCTL_setnodeaffinity */
+/* XEN_DOMCTL_getnodeaffinity */
+struct xen_domctl_nodeaffinity {
+ struct xenctl_bitmap nodemap;/* IN */
+};
+typedef struct xen_domctl_nodeaffinity xen_domctl_nodeaffinity_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_nodeaffinity_t);
+
+
+/* Get/set which physical cpus a vcpu can execute on. */
+/* XEN_DOMCTL_setvcpuaffinity */
+/* XEN_DOMCTL_getvcpuaffinity */
+struct xen_domctl_vcpuaffinity {
+ /* IN variables. */
+ uint32_t vcpu;
+ /* Set/get the hard affinity for vcpu */
+#define _XEN_VCPUAFFINITY_HARD 0
+#define XEN_VCPUAFFINITY_HARD (1U<<_XEN_VCPUAFFINITY_HARD)
+ /* Set/get the soft affinity for vcpu */
+#define _XEN_VCPUAFFINITY_SOFT 1
+#define XEN_VCPUAFFINITY_SOFT (1U<<_XEN_VCPUAFFINITY_SOFT)
+ uint32_t flags;
+ /*
+ * IN/OUT variables.
+ *
+ * Both are IN/OUT for XEN_DOMCTL_setvcpuaffinity, in which case they
+ * contain effective hard or/and soft affinity. That is, upon successful
+ * return, cpumap_soft, contains the intersection of the soft affinity,
+ * hard affinity and the cpupool's online CPUs for the domain (if
+ * XEN_VCPUAFFINITY_SOFT was set in flags). cpumap_hard contains the
+ * intersection between hard affinity and the cpupool's online CPUs (if
+ * XEN_VCPUAFFINITY_HARD was set in flags).
+ *
+ * Both are OUT-only for XEN_DOMCTL_getvcpuaffinity, in which case they
+ * contain the plain hard and/or soft affinity masks that were set during
+ * previous successful calls to XEN_DOMCTL_setvcpuaffinity (or the
+ * default values), without intersecting or altering them in any way.
+ */
+ struct xenctl_bitmap cpumap_hard;
+ struct xenctl_bitmap cpumap_soft;
+};
+typedef struct xen_domctl_vcpuaffinity xen_domctl_vcpuaffinity_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpuaffinity_t);
+
+
+/* XEN_DOMCTL_max_vcpus */
+struct xen_domctl_max_vcpus {
+ uint32_t max; /* maximum number of vcpus */
+};
+typedef struct xen_domctl_max_vcpus xen_domctl_max_vcpus_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_vcpus_t);
+
+
+/* XEN_DOMCTL_scheduler_op */
+/* Scheduler types. */
+#define XEN_SCHEDULER_SEDF 4
+#define XEN_SCHEDULER_CREDIT 5
+#define XEN_SCHEDULER_CREDIT2 6
+#define XEN_SCHEDULER_ARINC653 7
+#define XEN_SCHEDULER_RTDS 8
+
+/* Set or get info? */
+#define XEN_DOMCTL_SCHEDOP_putinfo 0
+#define XEN_DOMCTL_SCHEDOP_getinfo 1
+struct xen_domctl_scheduler_op {
+ uint32_t sched_id; /* XEN_SCHEDULER_* */
+ uint32_t cmd; /* XEN_DOMCTL_SCHEDOP_* */
+ union {
+ struct xen_domctl_sched_sedf {
+ uint64_aligned_t period;
+ uint64_aligned_t slice;
+ uint64_aligned_t latency;
+ uint32_t extratime;
+ uint32_t weight;
+ } sedf;
+ struct xen_domctl_sched_credit {
+ uint16_t weight;
+ uint16_t cap;
+ } credit;
+ struct xen_domctl_sched_credit2 {
+ uint16_t weight;
+ } credit2;
+ struct xen_domctl_sched_rtds {
+ uint32_t period;
+ uint32_t budget;
+ } rtds;
+ } u;
+};
+typedef struct xen_domctl_scheduler_op xen_domctl_scheduler_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_scheduler_op_t);
+
+
+/* XEN_DOMCTL_setdomainhandle */
+struct xen_domctl_setdomainhandle {
+ xen_domain_handle_t handle;
+};
+typedef struct xen_domctl_setdomainhandle xen_domctl_setdomainhandle_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdomainhandle_t);
+
+
+/* XEN_DOMCTL_setdebugging */
+struct xen_domctl_setdebugging {
+ uint8_t enable;
+};
+typedef struct xen_domctl_setdebugging xen_domctl_setdebugging_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdebugging_t);
+
+
+/* XEN_DOMCTL_irq_permission */
+struct xen_domctl_irq_permission {
+ uint8_t pirq;
+ uint8_t allow_access; /* flag to specify enable/disable of IRQ access */
+};
+typedef struct xen_domctl_irq_permission xen_domctl_irq_permission_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_irq_permission_t);
+
+
+/* XEN_DOMCTL_iomem_permission */
+struct xen_domctl_iomem_permission {
+ uint64_aligned_t first_mfn;/* first page (physical page number) in range */
+ uint64_aligned_t nr_mfns; /* number of pages in range (>0) */
+ uint8_t allow_access; /* allow (!0) or deny (0) access to range? */
+};
+typedef struct xen_domctl_iomem_permission xen_domctl_iomem_permission_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_iomem_permission_t);
+
+
+/* XEN_DOMCTL_ioport_permission */
+struct xen_domctl_ioport_permission {
+ uint32_t first_port; /* first port int range */
+ uint32_t nr_ports; /* size of port range */
+ uint8_t allow_access; /* allow or deny access to range? */
+};
+typedef struct xen_domctl_ioport_permission xen_domctl_ioport_permission_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_permission_t);
+
+
+/* XEN_DOMCTL_hypercall_init */
+struct xen_domctl_hypercall_init {
+ uint64_aligned_t gmfn; /* GMFN to be initialised */
+};
+typedef struct xen_domctl_hypercall_init xen_domctl_hypercall_init_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_hypercall_init_t);
+
+
+/* XEN_DOMCTL_settimeoffset */
+struct xen_domctl_settimeoffset {
+ int32_t time_offset_seconds; /* applied to domain wallclock time */
+};
+typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t);
+
+/* XEN_DOMCTL_gethvmcontext */
+/* XEN_DOMCTL_sethvmcontext */
+typedef struct xen_domctl_hvmcontext {
+ uint32_t size; /* IN/OUT: size of buffer / bytes filled */
+ XEN_GUEST_HANDLE_64(uint8) buffer; /* IN/OUT: data, or call
+ * gethvmcontext with NULL
+ * buffer to get size req'd */
+} xen_domctl_hvmcontext_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t);
+
+
+/* XEN_DOMCTL_set_address_size */
+/* XEN_DOMCTL_get_address_size */
+typedef struct xen_domctl_address_size {
+ uint32_t size;
+} xen_domctl_address_size_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_address_size_t);
+
+
+/* XEN_DOMCTL_sendtrigger */
+#define XEN_DOMCTL_SENDTRIGGER_NMI 0
+#define XEN_DOMCTL_SENDTRIGGER_RESET 1
+#define XEN_DOMCTL_SENDTRIGGER_INIT 2
+#define XEN_DOMCTL_SENDTRIGGER_POWER 3
+#define XEN_DOMCTL_SENDTRIGGER_SLEEP 4
+struct xen_domctl_sendtrigger {
+ uint32_t trigger; /* IN */
+ uint32_t vcpu; /* IN */
+};
+typedef struct xen_domctl_sendtrigger xen_domctl_sendtrigger_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_sendtrigger_t);
+
+
+/* Assign PCI device to HVM guest. Sets up IOMMU structures. */
+/* XEN_DOMCTL_assign_device */
+/* XEN_DOMCTL_test_assign_device */
+/* XEN_DOMCTL_deassign_device */
+struct xen_domctl_assign_device {
+ uint32_t machine_sbdf; /* machine PCI ID of assigned device */
+};
+typedef struct xen_domctl_assign_device xen_domctl_assign_device_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_assign_device_t);
+
+/* Retrieve sibling devices infomation of machine_sbdf */
+/* XEN_DOMCTL_get_device_group */
+struct xen_domctl_get_device_group {
+ uint32_t machine_sbdf; /* IN */
+ uint32_t max_sdevs; /* IN */
+ uint32_t num_sdevs; /* OUT */
+ XEN_GUEST_HANDLE_64(uint32) sdev_array; /* OUT */
+};
+typedef struct xen_domctl_get_device_group xen_domctl_get_device_group_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_get_device_group_t);
+
+/* Pass-through interrupts: bind real irq -> hvm devfn. */
+/* XEN_DOMCTL_bind_pt_irq */
+/* XEN_DOMCTL_unbind_pt_irq */
+typedef enum pt_irq_type_e {
+ PT_IRQ_TYPE_PCI,
+ PT_IRQ_TYPE_ISA,
+ PT_IRQ_TYPE_MSI,
+ PT_IRQ_TYPE_MSI_TRANSLATE,
+} pt_irq_type_t;
+struct xen_domctl_bind_pt_irq {
+ uint32_t machine_irq;
+ pt_irq_type_t irq_type;
+ uint32_t hvm_domid;
+
+ union {
+ struct {
+ uint8_t isa_irq;
+ } isa;
+ struct {
+ uint8_t bus;
+ uint8_t device;
+ uint8_t intx;
+ } pci;
+ struct {
+ uint8_t gvec;
+ uint32_t gflags;
+ uint64_aligned_t gtable;
+ } msi;
+ } u;
+};
+typedef struct xen_domctl_bind_pt_irq xen_domctl_bind_pt_irq_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_bind_pt_irq_t);
+
+
+/* Bind machine I/O address range -> HVM address range. */
+/* XEN_DOMCTL_memory_mapping */
+#define DPCI_ADD_MAPPING 1
+#define DPCI_REMOVE_MAPPING 0
+struct xen_domctl_memory_mapping {
+ uint64_aligned_t first_gfn; /* first page (hvm guest phys page) in range */
+ uint64_aligned_t first_mfn; /* first page (machine page) in range */
+ uint64_aligned_t nr_mfns; /* number of pages in range (>0) */
+ uint32_t add_mapping; /* add or remove mapping */
+ uint32_t padding; /* padding for 64-bit aligned structure */
+};
+typedef struct xen_domctl_memory_mapping xen_domctl_memory_mapping_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_memory_mapping_t);
+
+
+/* Bind machine I/O port range -> HVM I/O port range. */
+/* XEN_DOMCTL_ioport_mapping */
+struct xen_domctl_ioport_mapping {
+ uint32_t first_gport; /* first guest IO port*/
+ uint32_t first_mport; /* first machine IO port */
+ uint32_t nr_ports; /* size of port range */
+ uint32_t add_mapping; /* add or remove mapping */
+};
+typedef struct xen_domctl_ioport_mapping xen_domctl_ioport_mapping_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_mapping_t);
+
+
+/*
+ * Pin caching type of RAM space for x86 HVM domU.
+ */
+/* XEN_DOMCTL_pin_mem_cacheattr */
+/* Caching types: these happen to be the same as x86 MTRR/PAT type codes. */
+#define XEN_DOMCTL_MEM_CACHEATTR_UC 0
+#define XEN_DOMCTL_MEM_CACHEATTR_WC 1
+#define XEN_DOMCTL_MEM_CACHEATTR_WT 4
+#define XEN_DOMCTL_MEM_CACHEATTR_WP 5
+#define XEN_DOMCTL_MEM_CACHEATTR_WB 6
+#define XEN_DOMCTL_MEM_CACHEATTR_UCM 7
+#define XEN_DOMCTL_DELETE_MEM_CACHEATTR (~(uint32_t)0)
+struct xen_domctl_pin_mem_cacheattr {
+ uint64_aligned_t start, end;
+ uint32_t type; /* XEN_DOMCTL_MEM_CACHEATTR_* */
+};
+typedef struct xen_domctl_pin_mem_cacheattr xen_domctl_pin_mem_cacheattr_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_pin_mem_cacheattr_t);
+
+
+/* XEN_DOMCTL_set_ext_vcpucontext */
+/* XEN_DOMCTL_get_ext_vcpucontext */
+struct xen_domctl_ext_vcpucontext {
+ /* IN: VCPU that this call applies to. */
+ uint32_t vcpu;
+ /*
+ * SET: Size of struct (IN)
+ * GET: Size of struct (OUT, up to 128 bytes)
+ */
+ uint32_t size;
+#if defined(__i386__) || defined(__x86_64__)
+ /* SYSCALL from 32-bit mode and SYSENTER callback information. */
+ /* NB. SYSCALL from 64-bit mode is contained in vcpu_guest_context_t */
+ uint64_aligned_t syscall32_callback_eip;
+ uint64_aligned_t sysenter_callback_eip;
+ uint16_t syscall32_callback_cs;
+ uint16_t sysenter_callback_cs;
+ uint8_t syscall32_disables_events;
+ uint8_t sysenter_disables_events;
+#if defined(__GNUC__)
+ union {
+ uint64_aligned_t mcg_cap;
+ struct hvm_vmce_vcpu vmce;
+ };
+#else
+ struct hvm_vmce_vcpu vmce;
+#endif
+#endif
+};
+typedef struct xen_domctl_ext_vcpucontext xen_domctl_ext_vcpucontext_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_ext_vcpucontext_t);
+
+/*
+ * Set the target domain for a domain
+ */
+/* XEN_DOMCTL_set_target */
+struct xen_domctl_set_target {
+ domid_t target;
+};
+typedef struct xen_domctl_set_target xen_domctl_set_target_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_target_t);
+
+#if defined(__i386__) || defined(__x86_64__)
+# define XEN_CPUID_INPUT_UNUSED 0xFFFFFFFF
+/* XEN_DOMCTL_set_cpuid */
+struct xen_domctl_cpuid {
+ uint32_t input[2];
+ uint32_t eax;
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+};
+typedef struct xen_domctl_cpuid xen_domctl_cpuid_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_cpuid_t);
+#endif
+
+/*
+ * Arranges that if the domain suspends (specifically, if it shuts
+ * down with code SHUTDOWN_suspend), this event channel will be
+ * notified.
+ *
+ * This is _instead of_ the usual notification to the global
+ * VIRQ_DOM_EXC. (In most systems that pirq is owned by xenstored.)
+ *
+ * Only one subscription per domain is possible. Last subscriber
+ * wins; others are silently displaced.
+ *
+ * NB that contrary to the rather general name, it only applies to
+ * domain shutdown with code suspend. Shutdown for other reasons
+ * (including crash), and domain death, are notified to VIRQ_DOM_EXC
+ * regardless.
+ */
+/* XEN_DOMCTL_subscribe */
+struct xen_domctl_subscribe {
+ uint32_t port; /* IN */
+};
+typedef struct xen_domctl_subscribe xen_domctl_subscribe_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_subscribe_t);
+
+/*
+ * Define the maximum machine address size which should be allocated
+ * to a guest.
+ */
+/* XEN_DOMCTL_set_machine_address_size */
+/* XEN_DOMCTL_get_machine_address_size */
+
+/*
+ * Do not inject spurious page faults into this domain.
+ */
+/* XEN_DOMCTL_suppress_spurious_page_faults */
+
+/* XEN_DOMCTL_debug_op */
+#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF 0
+#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON 1
+struct xen_domctl_debug_op {
+ uint32_t op; /* IN */
+ uint32_t vcpu; /* IN */
+};
+typedef struct xen_domctl_debug_op xen_domctl_debug_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_debug_op_t);
+
+/*
+ * Request a particular record from the HVM context
+ */
+/* XEN_DOMCTL_gethvmcontext_partial */
+typedef struct xen_domctl_hvmcontext_partial {
+ uint32_t type; /* IN: Type of record required */
+ uint32_t instance; /* IN: Instance of that type */
+ XEN_GUEST_HANDLE_64(uint8) buffer; /* OUT: buffer to write record into */
+} xen_domctl_hvmcontext_partial_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_partial_t);
+
+/* XEN_DOMCTL_disable_migrate */
+typedef struct xen_domctl_disable_migrate {
+ uint32_t disable; /* IN: 1: disable migration and restore */
+} xen_domctl_disable_migrate_t;
+
+
+/* XEN_DOMCTL_gettscinfo */
+/* XEN_DOMCTL_settscinfo */
+struct xen_guest_tsc_info {
+ uint32_t tsc_mode;
+ uint32_t gtsc_khz;
+ uint32_t incarnation;
+ uint32_t pad;
+ uint64_aligned_t elapsed_nsec;
+};
+typedef struct xen_guest_tsc_info xen_guest_tsc_info_t;
+DEFINE_XEN_GUEST_HANDLE(xen_guest_tsc_info_t);
+typedef struct xen_domctl_tsc_info {
+ XEN_GUEST_HANDLE_64(xen_guest_tsc_info_t) out_info; /* OUT */
+ xen_guest_tsc_info_t info; /* IN */
+} xen_domctl_tsc_info_t;
+
+/* XEN_DOMCTL_gdbsx_guestmemio guest mem io */
+struct xen_domctl_gdbsx_memio {
+ /* IN */
+ uint64_aligned_t pgd3val;/* optional: init_mm.pgd[3] value */
+ uint64_aligned_t gva; /* guest virtual address */
+ uint64_aligned_t uva; /* user buffer virtual address */
+ uint32_t len; /* number of bytes to read/write */
+ uint8_t gwr; /* 0 = read from guest. 1 = write to guest */
+ /* OUT */
+ uint32_t remain; /* bytes remaining to be copied */
+};
+
+/* XEN_DOMCTL_gdbsx_pausevcpu */
+/* XEN_DOMCTL_gdbsx_unpausevcpu */
+struct xen_domctl_gdbsx_pauseunp_vcpu { /* pause/unpause a vcpu */
+ uint32_t vcpu; /* which vcpu */
+};
+
+/* XEN_DOMCTL_gdbsx_domstatus */
+struct xen_domctl_gdbsx_domstatus {
+ /* OUT */
+ uint8_t paused; /* is the domain paused */
+ uint32_t vcpu_id; /* any vcpu in an event? */
+ uint32_t vcpu_ev; /* if yes, what event? */
+};
+
+/*
+ * Memory event operations
+ */
+
+/* XEN_DOMCTL_mem_event_op */
+
+/*
+ * Domain memory paging
+ * Page memory in and out.
+ * Domctl interface to set up and tear down the
+ * pager<->hypervisor interface. Use XENMEM_paging_op*
+ * to perform per-page operations.
+ *
+ * The XEN_DOMCTL_MEM_EVENT_OP_PAGING_ENABLE domctl returns several
+ * non-standard error codes to indicate why paging could not be enabled:
+ * ENODEV - host lacks HAP support (EPT/NPT) or HAP is disabled in guest
+ * EMLINK - guest has iommu passthrough enabled
+ * EXDEV - guest has PoD enabled
+ * EBUSY - guest has or had paging enabled, ring buffer still active
+ */
+#define XEN_DOMCTL_MEM_EVENT_OP_PAGING 1
+
+#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_ENABLE 0
+#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_DISABLE 1
+
+/*
+ * Access permissions.
+ *
+ * As with paging, use the domctl for teardown/setup of the
+ * helper<->hypervisor interface.
+ *
+ * There are HVM hypercalls to set the per-page access permissions of every
+ * page in a domain. When one of these permissions--independent, read,
+ * write, and execute--is violated, the VCPU is paused and a memory event
+ * is sent with what happened. (See public/mem_event.h) .
+ *
+ * The memory event handler can then resume the VCPU and redo the access
+ * with a XENMEM_access_op_resume hypercall.
+ *
+ * The XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE domctl returns several
+ * non-standard error codes to indicate why access could not be enabled:
+ * ENODEV - host lacks HAP support (EPT/NPT) or HAP is disabled in guest
+ * EBUSY - guest has or had access enabled, ring buffer still active
+ */
+#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS 2
+
+#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE 0
+#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_DISABLE 1
+#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE_INTROSPECTION 2
+
+/*
+ * Sharing ENOMEM helper.
+ *
+ * As with paging, use the domctl for teardown/setup of the
+ * helper<->hypervisor interface.
+ *
+ * If setup, this ring is used to communicate failed allocations
+ * in the unshare path. XENMEM_sharing_op_resume is used to wake up
+ * vcpus that could not unshare.
+ *
+ * Note that shring can be turned on (as per the domctl below)
+ * *without* this ring being setup.
+ */
+#define XEN_DOMCTL_MEM_EVENT_OP_SHARING 3
+
+#define XEN_DOMCTL_MEM_EVENT_OP_SHARING_ENABLE 0
+#define XEN_DOMCTL_MEM_EVENT_OP_SHARING_DISABLE 1
+
+/* Use for teardown/setup of helper<->hypervisor interface for paging,
+ * access and sharing.*/
+struct xen_domctl_mem_event_op {
+ uint32_t op; /* XEN_DOMCTL_MEM_EVENT_OP_*_* */
+ uint32_t mode; /* XEN_DOMCTL_MEM_EVENT_OP_* */
+
+ uint32_t port; /* OUT: event channel for ring */
+};
+typedef struct xen_domctl_mem_event_op xen_domctl_mem_event_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_mem_event_op_t);
+
+/*
+ * Memory sharing operations
+ */
+/* XEN_DOMCTL_mem_sharing_op.
+ * The CONTROL sub-domctl is used for bringup/teardown. */
+#define XEN_DOMCTL_MEM_SHARING_CONTROL 0
+
+struct xen_domctl_mem_sharing_op {
+ uint8_t op; /* XEN_DOMCTL_MEM_SHARING_* */
+
+ union {
+ uint8_t enable; /* CONTROL */
+ } u;
+};
+typedef struct xen_domctl_mem_sharing_op xen_domctl_mem_sharing_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_mem_sharing_op_t);
+
+struct xen_domctl_audit_p2m {
+ /* OUT error counts */
+ uint64_t orphans;
+ uint64_t m2p_bad;
+ uint64_t p2m_bad;
+};
+typedef struct xen_domctl_audit_p2m xen_domctl_audit_p2m_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_audit_p2m_t);
+
+struct xen_domctl_set_virq_handler {
+ uint32_t virq; /* IN */
+};
+typedef struct xen_domctl_set_virq_handler xen_domctl_set_virq_handler_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_virq_handler_t);
+
+#if defined(__i386__) || defined(__x86_64__)
+/* XEN_DOMCTL_setvcpuextstate */
+/* XEN_DOMCTL_getvcpuextstate */
+struct xen_domctl_vcpuextstate {
+ /* IN: VCPU that this call applies to. */
+ uint32_t vcpu;
+ /*
+ * SET: Ignored.
+ * GET: xfeature support mask of struct (IN/OUT)
+ * xfeature mask is served as identifications of the saving format
+ * so that compatible CPUs can have a check on format to decide
+ * whether it can restore.
+ */
+ uint64_aligned_t xfeature_mask;
+ /*
+ * SET: Size of struct (IN)
+ * GET: Size of struct (IN/OUT)
+ */
+ uint64_aligned_t size;
+ XEN_GUEST_HANDLE_64(uint64) buffer;
+};
+typedef struct xen_domctl_vcpuextstate xen_domctl_vcpuextstate_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpuextstate_t);
+#endif
+
+/* XEN_DOMCTL_set_access_required: sets whether a memory event listener
+ * must be present to handle page access events: if false, the page
+ * access will revert to full permissions if no one is listening;
+ * */
+struct xen_domctl_set_access_required {
+ uint8_t access_required;
+};
+typedef struct xen_domctl_set_access_required xen_domctl_set_access_required_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_access_required_t);
+
+struct xen_domctl_set_broken_page_p2m {
+ uint64_aligned_t pfn;
+};
+typedef struct xen_domctl_set_broken_page_p2m xen_domctl_set_broken_page_p2m_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_broken_page_p2m_t);
+
+/*
+ * XEN_DOMCTL_set_max_evtchn: sets the maximum event channel port
+ * number the guest may use. Use this limit the amount of resources
+ * (global mapping space, xenheap) a guest may use for event channels.
+ */
+struct xen_domctl_set_max_evtchn {
+ uint32_t max_port;
+};
+typedef struct xen_domctl_set_max_evtchn xen_domctl_set_max_evtchn_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_max_evtchn_t);
+
+/*
+ * ARM: Clean and invalidate caches associated with given region of
+ * guest memory.
+ */
+struct xen_domctl_cacheflush {
+ /* IN: page range to flush. */
+ xen_pfn_t start_pfn, nr_pfns;
+};
+typedef struct xen_domctl_cacheflush xen_domctl_cacheflush_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_cacheflush_t);
+
+#if defined(__i386__) || defined(__x86_64__)
+struct xen_domctl_vcpu_msr {
+ uint32_t index;
+ uint32_t reserved;
+ uint64_aligned_t value;
+};
+typedef struct xen_domctl_vcpu_msr xen_domctl_vcpu_msr_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpu_msr_t);
+
+/*
+ * XEN_DOMCTL_set_vcpu_msrs / XEN_DOMCTL_get_vcpu_msrs.
+ *
+ * Input:
+ * - A NULL 'msrs' guest handle is a request for the maximum 'msr_count'.
+ * - Otherwise, 'msr_count' is the number of entries in 'msrs'.
+ *
+ * Output for get:
+ * - If 'msr_count' is less than the number Xen needs to write, -ENOBUFS shall
+ * be returned and 'msr_count' updated to reflect the intended number.
+ * - On success, 'msr_count' shall indicate the number of MSRs written, which
+ * may be less than the maximum if some are not currently used by the vcpu.
+ *
+ * Output for set:
+ * - If Xen encounters an error with a specific MSR, -EINVAL shall be returned
+ * and 'msr_count' shall be set to the offending index, to aid debugging.
+ */
+struct xen_domctl_vcpu_msrs {
+ uint32_t vcpu; /* IN */
+ uint32_t msr_count; /* IN/OUT */
+ XEN_GUEST_HANDLE_64(xen_domctl_vcpu_msr_t) msrs; /* IN/OUT */
+};
+typedef struct xen_domctl_vcpu_msrs xen_domctl_vcpu_msrs_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpu_msrs_t);
+#endif
+
+/*
+ * Use in XEN_DOMCTL_setvnumainfo to set
+ * vNUMA domain topology.
+ */
+struct xen_domctl_vnuma {
+ uint32_t nr_vnodes;
+ uint32_t nr_vmemranges;
+ uint32_t nr_vcpus;
+ uint32_t pad;
+ XEN_GUEST_HANDLE_64(uint) vdistance;
+ XEN_GUEST_HANDLE_64(uint) vcpu_to_vnode;
+
+ /*
+ * vnodes to physical NUMA nodes mask.
+ * This kept on per-domain basis for
+ * interested consumers, such as numa aware ballooning.
+ */
+ XEN_GUEST_HANDLE_64(uint) vnode_to_pnode;
+
+ /*
+ * memory rages for each vNUMA node
+ */
+ XEN_GUEST_HANDLE_64(xen_vmemrange_t) vmemrange;
+};
+typedef struct xen_domctl_vnuma xen_domctl_vnuma_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_vnuma_t);
+
+struct xen_domctl_psr_cmt_op {
+#define XEN_DOMCTL_PSR_CMT_OP_DETACH 0
+#define XEN_DOMCTL_PSR_CMT_OP_ATTACH 1
+#define XEN_DOMCTL_PSR_CMT_OP_QUERY_RMID 2
+ uint32_t cmd;
+ uint32_t data;
+};
+typedef struct xen_domctl_psr_cmt_op xen_domctl_psr_cmt_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cmt_op_t);
+
+struct xen_domctl {
+ uint32_t cmd;
+#define XEN_DOMCTL_createdomain 1
+#define XEN_DOMCTL_destroydomain 2
+#define XEN_DOMCTL_pausedomain 3
+#define XEN_DOMCTL_unpausedomain 4
+#define XEN_DOMCTL_getdomaininfo 5
+#define XEN_DOMCTL_getmemlist 6
+#define XEN_DOMCTL_getpageframeinfo 7
+#define XEN_DOMCTL_getpageframeinfo2 8
+#define XEN_DOMCTL_setvcpuaffinity 9
+#define XEN_DOMCTL_shadow_op 10
+#define XEN_DOMCTL_max_mem 11
+#define XEN_DOMCTL_setvcpucontext 12
+#define XEN_DOMCTL_getvcpucontext 13
+#define XEN_DOMCTL_getvcpuinfo 14
+#define XEN_DOMCTL_max_vcpus 15
+#define XEN_DOMCTL_scheduler_op 16
+#define XEN_DOMCTL_setdomainhandle 17
+#define XEN_DOMCTL_setdebugging 18
+#define XEN_DOMCTL_irq_permission 19
+#define XEN_DOMCTL_iomem_permission 20
+#define XEN_DOMCTL_ioport_permission 21
+#define XEN_DOMCTL_hypercall_init 22
+#define XEN_DOMCTL_arch_setup 23 /* Obsolete IA64 only */
+#define XEN_DOMCTL_settimeoffset 24
+#define XEN_DOMCTL_getvcpuaffinity 25
+#define XEN_DOMCTL_real_mode_area 26 /* Obsolete PPC only */
+#define XEN_DOMCTL_resumedomain 27
+#define XEN_DOMCTL_sendtrigger 28
+#define XEN_DOMCTL_subscribe 29
+#define XEN_DOMCTL_gethvmcontext 33
+#define XEN_DOMCTL_sethvmcontext 34
+#define XEN_DOMCTL_set_address_size 35
+#define XEN_DOMCTL_get_address_size 36
+#define XEN_DOMCTL_assign_device 37
+#define XEN_DOMCTL_bind_pt_irq 38
+#define XEN_DOMCTL_memory_mapping 39
+#define XEN_DOMCTL_ioport_mapping 40
+#define XEN_DOMCTL_pin_mem_cacheattr 41
+#define XEN_DOMCTL_set_ext_vcpucontext 42
+#define XEN_DOMCTL_get_ext_vcpucontext 43
+#define XEN_DOMCTL_set_opt_feature 44 /* Obsolete IA64 only */
+#define XEN_DOMCTL_test_assign_device 45
+#define XEN_DOMCTL_set_target 46
+#define XEN_DOMCTL_deassign_device 47
+#define XEN_DOMCTL_unbind_pt_irq 48
+#define XEN_DOMCTL_set_cpuid 49
+#define XEN_DOMCTL_get_device_group 50
+#define XEN_DOMCTL_set_machine_address_size 51
+#define XEN_DOMCTL_get_machine_address_size 52
+#define XEN_DOMCTL_suppress_spurious_page_faults 53
+#define XEN_DOMCTL_debug_op 54
+#define XEN_DOMCTL_gethvmcontext_partial 55
+#define XEN_DOMCTL_mem_event_op 56
+#define XEN_DOMCTL_mem_sharing_op 57
+#define XEN_DOMCTL_disable_migrate 58
+#define XEN_DOMCTL_gettscinfo 59
+#define XEN_DOMCTL_settscinfo 60
+#define XEN_DOMCTL_getpageframeinfo3 61
+#define XEN_DOMCTL_setvcpuextstate 62
+#define XEN_DOMCTL_getvcpuextstate 63
+#define XEN_DOMCTL_set_access_required 64
+#define XEN_DOMCTL_audit_p2m 65
+#define XEN_DOMCTL_set_virq_handler 66
+#define XEN_DOMCTL_set_broken_page_p2m 67
+#define XEN_DOMCTL_setnodeaffinity 68
+#define XEN_DOMCTL_getnodeaffinity 69
+#define XEN_DOMCTL_set_max_evtchn 70
+#define XEN_DOMCTL_cacheflush 71
+#define XEN_DOMCTL_get_vcpu_msrs 72
+#define XEN_DOMCTL_set_vcpu_msrs 73
+#define XEN_DOMCTL_setvnumainfo 74
+#define XEN_DOMCTL_psr_cmt_op 75
+#define XEN_DOMCTL_arm_configure_domain 76
+#define XEN_DOMCTL_gdbsx_guestmemio 1000
+#define XEN_DOMCTL_gdbsx_pausevcpu 1001
+#define XEN_DOMCTL_gdbsx_unpausevcpu 1002
+#define XEN_DOMCTL_gdbsx_domstatus 1003
+ uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */
+ domid_t domain;
+ union {
+ struct xen_domctl_createdomain createdomain;
+#if defined(__arm__) || defined(__aarch64__)
+ struct xen_domctl_arm_configuredomain configuredomain;
+#endif
+ struct xen_domctl_getdomaininfo getdomaininfo;
+ struct xen_domctl_getmemlist getmemlist;
+ struct xen_domctl_getpageframeinfo getpageframeinfo;
+ struct xen_domctl_getpageframeinfo2 getpageframeinfo2;
+ struct xen_domctl_getpageframeinfo3 getpageframeinfo3;
+ struct xen_domctl_nodeaffinity nodeaffinity;
+ struct xen_domctl_vcpuaffinity vcpuaffinity;
+ struct xen_domctl_shadow_op shadow_op;
+ struct xen_domctl_max_mem max_mem;
+ struct xen_domctl_vcpucontext vcpucontext;
+ struct xen_domctl_getvcpuinfo getvcpuinfo;
+ struct xen_domctl_max_vcpus max_vcpus;
+ struct xen_domctl_scheduler_op scheduler_op;
+ struct xen_domctl_setdomainhandle setdomainhandle;
+ struct xen_domctl_setdebugging setdebugging;
+ struct xen_domctl_irq_permission irq_permission;
+ struct xen_domctl_iomem_permission iomem_permission;
+ struct xen_domctl_ioport_permission ioport_permission;
+ struct xen_domctl_hypercall_init hypercall_init;
+ struct xen_domctl_settimeoffset settimeoffset;
+ struct xen_domctl_disable_migrate disable_migrate;
+ struct xen_domctl_tsc_info tsc_info;
+ struct xen_domctl_hvmcontext hvmcontext;
+ struct xen_domctl_hvmcontext_partial hvmcontext_partial;
+ struct xen_domctl_address_size address_size;
+ struct xen_domctl_sendtrigger sendtrigger;
+ struct xen_domctl_get_device_group get_device_group;
+ struct xen_domctl_assign_device assign_device;
+ struct xen_domctl_bind_pt_irq bind_pt_irq;
+ struct xen_domctl_memory_mapping memory_mapping;
+ struct xen_domctl_ioport_mapping ioport_mapping;
+ struct xen_domctl_pin_mem_cacheattr pin_mem_cacheattr;
+ struct xen_domctl_ext_vcpucontext ext_vcpucontext;
+ struct xen_domctl_set_target set_target;
+ struct xen_domctl_subscribe subscribe;
+ struct xen_domctl_debug_op debug_op;
+ struct xen_domctl_mem_event_op mem_event_op;
+ struct xen_domctl_mem_sharing_op mem_sharing_op;
+#if defined(__i386__) || defined(__x86_64__)
+ struct xen_domctl_cpuid cpuid;
+ struct xen_domctl_vcpuextstate vcpuextstate;
+ struct xen_domctl_vcpu_msrs vcpu_msrs;
+#endif
+ struct xen_domctl_set_access_required access_required;
+ struct xen_domctl_audit_p2m audit_p2m;
+ struct xen_domctl_set_virq_handler set_virq_handler;
+ struct xen_domctl_set_max_evtchn set_max_evtchn;
+ struct xen_domctl_gdbsx_memio gdbsx_guest_memio;
+ struct xen_domctl_set_broken_page_p2m set_broken_page_p2m;
+ struct xen_domctl_cacheflush cacheflush;
+ struct xen_domctl_gdbsx_pauseunp_vcpu gdbsx_pauseunp_vcpu;
+ struct xen_domctl_gdbsx_domstatus gdbsx_domstatus;
+ struct xen_domctl_vnuma vnuma;
+ struct xen_domctl_psr_cmt_op psr_cmt_op;
+ uint8_t pad[128];
+ } u;
+};
+typedef struct xen_domctl xen_domctl_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_t);
+
+#endif /* __XEN_PUBLIC_DOMCTL_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * elfnote.h
+ *
+ * Definitions used for the Xen ELF notes.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2006, Ian Campbell, XenSource Ltd.
+ */
+
+#ifndef __XEN_PUBLIC_ELFNOTE_H__
+#define __XEN_PUBLIC_ELFNOTE_H__
+
+/*
+ * `incontents 200 elfnotes ELF notes
+ *
+ * The notes should live in a PT_NOTE segment and have "Xen" in the
+ * name field.
+ *
+ * Numeric types are either 4 or 8 bytes depending on the content of
+ * the desc field.
+ *
+ * LEGACY indicated the fields in the legacy __xen_guest string which
+ * this a note type replaces.
+ *
+ * String values (for non-legacy) are NULL terminated ASCII, also known
+ * as ASCIZ type.
+ */
+
+/*
+ * NAME=VALUE pair (string).
+ */
+#define XEN_ELFNOTE_INFO 0
+
+/*
+ * The virtual address of the entry point (numeric).
+ *
+ * LEGACY: VIRT_ENTRY
+ */
+#define XEN_ELFNOTE_ENTRY 1
+
+/* The virtual address of the hypercall transfer page (numeric).
+ *
+ * LEGACY: HYPERCALL_PAGE. (n.b. legacy value is a physical page
+ * number not a virtual address)
+ */
+#define XEN_ELFNOTE_HYPERCALL_PAGE 2
+
+/* The virtual address where the kernel image should be mapped (numeric).
+ *
+ * Defaults to 0.
+ *
+ * LEGACY: VIRT_BASE
+ */
+#define XEN_ELFNOTE_VIRT_BASE 3
+
+/*
+ * The offset of the ELF paddr field from the actual required
+ * pseudo-physical address (numeric).
+ *
+ * This is used to maintain backwards compatibility with older kernels
+ * which wrote __PAGE_OFFSET into that field. This field defaults to 0
+ * if not present.
+ *
+ * LEGACY: ELF_PADDR_OFFSET. (n.b. legacy default is VIRT_BASE)
+ */
+#define XEN_ELFNOTE_PADDR_OFFSET 4
+
+/*
+ * The version of Xen that we work with (string).
+ *
+ * LEGACY: XEN_VER
+ */
+#define XEN_ELFNOTE_XEN_VERSION 5
+
+/*
+ * The name of the guest operating system (string).
+ *
+ * LEGACY: GUEST_OS
+ */
+#define XEN_ELFNOTE_GUEST_OS 6
+
+/*
+ * The version of the guest operating system (string).
+ *
+ * LEGACY: GUEST_VER
+ */
+#define XEN_ELFNOTE_GUEST_VERSION 7
+
+/*
+ * The loader type (string).
+ *
+ * LEGACY: LOADER
+ */
+#define XEN_ELFNOTE_LOADER 8
+
+/*
+ * The kernel supports PAE (x86/32 only, string = "yes", "no" or
+ * "bimodal").
+ *
+ * For compatibility with Xen 3.0.3 and earlier the "bimodal" setting
+ * may be given as "yes,bimodal" which will cause older Xen to treat
+ * this kernel as PAE.
+ *
+ * LEGACY: PAE (n.b. The legacy interface included a provision to
+ * indicate 'extended-cr3' support allowing L3 page tables to be
+ * placed above 4G. It is assumed that any kernel new enough to use
+ * these ELF notes will include this and therefore "yes" here is
+ * equivalent to "yes[entended-cr3]" in the __xen_guest interface.
+ */
+#define XEN_ELFNOTE_PAE_MODE 9
+
+/*
+ * The features supported/required by this kernel (string).
+ *
+ * The string must consist of a list of feature names (as given in
+ * features.h, without the "XENFEAT_" prefix) separated by '|'
+ * characters. If a feature is required for the kernel to function
+ * then the feature name must be preceded by a '!' character.
+ *
+ * LEGACY: FEATURES
+ */
+#define XEN_ELFNOTE_FEATURES 10
+
+/*
+ * The kernel requires the symbol table to be loaded (string = "yes" or "no")
+ * LEGACY: BSD_SYMTAB (n.b. The legacy treated the presence or absence
+ * of this string as a boolean flag rather than requiring "yes" or
+ * "no".
+ */
+#define XEN_ELFNOTE_BSD_SYMTAB 11
+
+/*
+ * The lowest address the hypervisor hole can begin at (numeric).
+ *
+ * This must not be set higher than HYPERVISOR_VIRT_START. Its presence
+ * also indicates to the hypervisor that the kernel can deal with the
+ * hole starting at a higher address.
+ */
+#define XEN_ELFNOTE_HV_START_LOW 12
+
+/*
+ * List of maddr_t-sized mask/value pairs describing how to recognize
+ * (non-present) L1 page table entries carrying valid MFNs (numeric).
+ */
+#define XEN_ELFNOTE_L1_MFN_VALID 13
+
+/*
+ * Whether or not the guest supports cooperative suspend cancellation.
+ * This is a numeric value.
+ *
+ * Default is 0
+ */
+#define XEN_ELFNOTE_SUSPEND_CANCEL 14
+
+/*
+ * The (non-default) location the initial phys-to-machine map should be
+ * placed at by the hypervisor (Dom0) or the tools (DomU).
+ * The kernel must be prepared for this mapping to be established using
+ * large pages, despite such otherwise not being available to guests.
+ * The kernel must also be able to handle the page table pages used for
+ * this mapping not being accessible through the initial mapping.
+ * (Only x86-64 supports this at present.)
+ */
+#define XEN_ELFNOTE_INIT_P2M 15
+
+/*
+ * Whether or not the guest can deal with being passed an initrd not
+ * mapped through its initial page tables.
+ */
+#define XEN_ELFNOTE_MOD_START_PFN 16
+
+/*
+ * The features supported by this kernel (numeric).
+ *
+ * Other than XEN_ELFNOTE_FEATURES on pre-4.2 Xen, this note allows a
+ * kernel to specify support for features that older hypervisors don't
+ * know about. The set of features 4.2 and newer hypervisors will
+ * consider supported by the kernel is the combination of the sets
+ * specified through this and the string note.
+ *
+ * LEGACY: FEATURES
+ */
+#define XEN_ELFNOTE_SUPPORTED_FEATURES 17
+
+/*
+ * The number of the highest elfnote defined.
+ */
+#define XEN_ELFNOTE_MAX XEN_ELFNOTE_SUPPORTED_FEATURES
+
+/*
+ * System information exported through crash notes.
+ *
+ * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_INFO
+ * note in case of a system crash. This note will contain various
+ * information about the system, see xen/include/xen/elfcore.h.
+ */
+#define XEN_ELFNOTE_CRASH_INFO 0x1000001
+
+/*
+ * System registers exported through crash notes.
+ *
+ * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_REGS
+ * note per cpu in case of a system crash. This note is architecture
+ * specific and will contain registers not saved in the "CORE" note.
+ * See xen/include/xen/elfcore.h for more information.
+ */
+#define XEN_ELFNOTE_CRASH_REGS 0x1000002
+
+
+/*
+ * xen dump-core none note.
+ * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_NONE
+ * in its dump file to indicate that the file is xen dump-core
+ * file. This note doesn't have any other information.
+ * See tools/libxc/xc_core.h for more information.
+ */
+#define XEN_ELFNOTE_DUMPCORE_NONE 0x2000000
+
+/*
+ * xen dump-core header note.
+ * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_HEADER
+ * in its dump file.
+ * See tools/libxc/xc_core.h for more information.
+ */
+#define XEN_ELFNOTE_DUMPCORE_HEADER 0x2000001
+
+/*
+ * xen dump-core xen version note.
+ * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_XEN_VERSION
+ * in its dump file. It contains the xen version obtained via the
+ * XENVER hypercall.
+ * See tools/libxc/xc_core.h for more information.
+ */
+#define XEN_ELFNOTE_DUMPCORE_XEN_VERSION 0x2000002
+
+/*
+ * xen dump-core format version note.
+ * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION
+ * in its dump file. It contains a format version identifier.
+ * See tools/libxc/xc_core.h for more information.
+ */
+#define XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION 0x2000003
+
+#endif /* __XEN_PUBLIC_ELFNOTE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * event_channel.h
+ *
+ * Event channels between domains.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2003-2004, K A Fraser.
+ */
+
+#ifndef __XEN_PUBLIC_EVENT_CHANNEL_H__
+#define __XEN_PUBLIC_EVENT_CHANNEL_H__
+
+#include "xen.h"
+
+/*
+ * `incontents 150 evtchn Event Channels
+ *
+ * Event channels are the basic primitive provided by Xen for event
+ * notifications. An event is the Xen equivalent of a hardware
+ * interrupt. They essentially store one bit of information, the event
+ * of interest is signalled by transitioning this bit from 0 to 1.
+ *
+ * Notifications are received by a guest via an upcall from Xen,
+ * indicating when an event arrives (setting the bit). Further
+ * notifications are masked until the bit is cleared again (therefore,
+ * guests must check the value of the bit after re-enabling event
+ * delivery to ensure no missed notifications).
+ *
+ * Event notifications can be masked by setting a flag; this is
+ * equivalent to disabling interrupts and can be used to ensure
+ * atomicity of certain operations in the guest kernel.
+ *
+ * Event channels are represented by the evtchn_* fields in
+ * struct shared_info and struct vcpu_info.
+ */
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_event_channel_op(enum event_channel_op cmd, void *args)
+ * `
+ * @cmd == EVTCHNOP_* (event-channel operation).
+ * @args == struct evtchn_* Operation-specific extra arguments (NULL if none).
+ */
+
+/* ` enum event_channel_op { // EVTCHNOP_* => struct evtchn_* */
+#define EVTCHNOP_bind_interdomain 0
+#define EVTCHNOP_bind_virq 1
+#define EVTCHNOP_bind_pirq 2
+#define EVTCHNOP_close 3
+#define EVTCHNOP_send 4
+#define EVTCHNOP_status 5
+#define EVTCHNOP_alloc_unbound 6
+#define EVTCHNOP_bind_ipi 7
+#define EVTCHNOP_bind_vcpu 8
+#define EVTCHNOP_unmask 9
+#define EVTCHNOP_reset 10
+#define EVTCHNOP_init_control 11
+#define EVTCHNOP_expand_array 12
+#define EVTCHNOP_set_priority 13
+/* ` } */
+
+typedef uint32_t evtchn_port_t;
+DEFINE_XEN_GUEST_HANDLE(evtchn_port_t);
+
+/*
+ * EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as
+ * accepting interdomain bindings from domain <remote_dom>. A fresh port
+ * is allocated in <dom> and returned as <port>.
+ * NOTES:
+ * 1. If the caller is unprivileged then <dom> must be DOMID_SELF.
+ * 2. <rdom> may be DOMID_SELF, allowing loopback connections.
+ */
+struct evtchn_alloc_unbound {
+ /* IN parameters */
+ domid_t dom, remote_dom;
+ /* OUT parameters */
+ evtchn_port_t port;
+};
+typedef struct evtchn_alloc_unbound evtchn_alloc_unbound_t;
+
+/*
+ * EVTCHNOP_bind_interdomain: Construct an interdomain event channel between
+ * the calling domain and <remote_dom>. <remote_dom,remote_port> must identify
+ * a port that is unbound and marked as accepting bindings from the calling
+ * domain. A fresh port is allocated in the calling domain and returned as
+ * <local_port>.
+ *
+ * In case the peer domain has already tried to set our event channel
+ * pending, before it was bound, EVTCHNOP_bind_interdomain always sets
+ * the local event channel pending.
+ *
+ * The usual pattern of use, in the guest's upcall (or subsequent
+ * handler) is as follows: (Re-enable the event channel for subsequent
+ * signalling and then) check for the existence of whatever condition
+ * is being waited for by other means, and take whatever action is
+ * needed (if any).
+ *
+ * NOTES:
+ * 1. <remote_dom> may be DOMID_SELF, allowing loopback connections.
+ */
+struct evtchn_bind_interdomain {
+ /* IN parameters. */
+ domid_t remote_dom;
+ evtchn_port_t remote_port;
+ /* OUT parameters. */
+ evtchn_port_t local_port;
+};
+typedef struct evtchn_bind_interdomain evtchn_bind_interdomain_t;
+
+/*
+ * EVTCHNOP_bind_virq: Bind a local event channel to VIRQ <irq> on specified
+ * vcpu.
+ * NOTES:
+ * 1. Virtual IRQs are classified as per-vcpu or global. See the VIRQ list
+ * in xen.h for the classification of each VIRQ.
+ * 2. Global VIRQs must be allocated on VCPU0 but can subsequently be
+ * re-bound via EVTCHNOP_bind_vcpu.
+ * 3. Per-vcpu VIRQs may be bound to at most one event channel per vcpu.
+ * The allocated event channel is bound to the specified vcpu and the
+ * binding cannot be changed.
+ */
+struct evtchn_bind_virq {
+ /* IN parameters. */
+ uint32_t virq; /* enum virq */
+ uint32_t vcpu;
+ /* OUT parameters. */
+ evtchn_port_t port;
+};
+typedef struct evtchn_bind_virq evtchn_bind_virq_t;
+
+/*
+ * EVTCHNOP_bind_pirq: Bind a local event channel to a real IRQ (PIRQ <irq>).
+ * NOTES:
+ * 1. A physical IRQ may be bound to at most one event channel per domain.
+ * 2. Only a sufficiently-privileged domain may bind to a physical IRQ.
+ */
+struct evtchn_bind_pirq {
+ /* IN parameters. */
+ uint32_t pirq;
+#define BIND_PIRQ__WILL_SHARE 1
+ uint32_t flags; /* BIND_PIRQ__* */
+ /* OUT parameters. */
+ evtchn_port_t port;
+};
+typedef struct evtchn_bind_pirq evtchn_bind_pirq_t;
+
+/*
+ * EVTCHNOP_bind_ipi: Bind a local event channel to receive events.
+ * NOTES:
+ * 1. The allocated event channel is bound to the specified vcpu. The binding
+ * may not be changed.
+ */
+struct evtchn_bind_ipi {
+ uint32_t vcpu;
+ /* OUT parameters. */
+ evtchn_port_t port;
+};
+typedef struct evtchn_bind_ipi evtchn_bind_ipi_t;
+
+/*
+ * EVTCHNOP_close: Close a local event channel <port>. If the channel is
+ * interdomain then the remote end is placed in the unbound state
+ * (EVTCHNSTAT_unbound), awaiting a new connection.
+ */
+struct evtchn_close {
+ /* IN parameters. */
+ evtchn_port_t port;
+};
+typedef struct evtchn_close evtchn_close_t;
+
+/*
+ * EVTCHNOP_send: Send an event to the remote end of the channel whose local
+ * endpoint is <port>.
+ */
+struct evtchn_send {
+ /* IN parameters. */
+ evtchn_port_t port;
+};
+typedef struct evtchn_send evtchn_send_t;
+
+/*
+ * EVTCHNOP_status: Get the current status of the communication channel which
+ * has an endpoint at <dom, port>.
+ * NOTES:
+ * 1. <dom> may be specified as DOMID_SELF.
+ * 2. Only a sufficiently-privileged domain may obtain the status of an event
+ * channel for which <dom> is not DOMID_SELF.
+ */
+struct evtchn_status {
+ /* IN parameters */
+ domid_t dom;
+ evtchn_port_t port;
+ /* OUT parameters */
+#define EVTCHNSTAT_closed 0 /* Channel is not in use. */
+#define EVTCHNSTAT_unbound 1 /* Channel is waiting interdom connection.*/
+#define EVTCHNSTAT_interdomain 2 /* Channel is connected to remote domain. */
+#define EVTCHNSTAT_pirq 3 /* Channel is bound to a phys IRQ line. */
+#define EVTCHNSTAT_virq 4 /* Channel is bound to a virtual IRQ line */
+#define EVTCHNSTAT_ipi 5 /* Channel is bound to a virtual IPI line */
+ uint32_t status;
+ uint32_t vcpu; /* VCPU to which this channel is bound. */
+ union {
+ struct {
+ domid_t dom;
+ } unbound; /* EVTCHNSTAT_unbound */
+ struct {
+ domid_t dom;
+ evtchn_port_t port;
+ } interdomain; /* EVTCHNSTAT_interdomain */
+ uint32_t pirq; /* EVTCHNSTAT_pirq */
+ uint32_t virq; /* EVTCHNSTAT_virq */
+ } u;
+};
+typedef struct evtchn_status evtchn_status_t;
+
+/*
+ * EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an
+ * event is pending.
+ * NOTES:
+ * 1. IPI-bound channels always notify the vcpu specified at bind time.
+ * This binding cannot be changed.
+ * 2. Per-VCPU VIRQ channels always notify the vcpu specified at bind time.
+ * This binding cannot be changed.
+ * 3. All other channels notify vcpu0 by default. This default is set when
+ * the channel is allocated (a port that is freed and subsequently reused
+ * has its binding reset to vcpu0).
+ */
+struct evtchn_bind_vcpu {
+ /* IN parameters. */
+ evtchn_port_t port;
+ uint32_t vcpu;
+};
+typedef struct evtchn_bind_vcpu evtchn_bind_vcpu_t;
+
+/*
+ * EVTCHNOP_unmask: Unmask the specified local event-channel port and deliver
+ * a notification to the appropriate VCPU if an event is pending.
+ */
+struct evtchn_unmask {
+ /* IN parameters. */
+ evtchn_port_t port;
+};
+typedef struct evtchn_unmask evtchn_unmask_t;
+
+/*
+ * EVTCHNOP_reset: Close all event channels associated with specified domain.
+ * NOTES:
+ * 1. <dom> may be specified as DOMID_SELF.
+ * 2. Only a sufficiently-privileged domain may specify other than DOMID_SELF.
+ * 3. Destroys all control blocks and event array, resets event channel
+ * operations to 2-level ABI if called with <dom> == DOMID_SELF and FIFO
+ * ABI was used. Guests should not bind events during EVTCHNOP_reset call
+ * as these events are likely to be lost.
+ */
+struct evtchn_reset {
+ /* IN parameters. */
+ domid_t dom;
+};
+typedef struct evtchn_reset evtchn_reset_t;
+
+/*
+ * EVTCHNOP_init_control: initialize the control block for the FIFO ABI.
+ *
+ * Note: any events that are currently pending will not be resent and
+ * will be lost. Guests should call this before binding any event to
+ * avoid losing any events.
+ */
+struct evtchn_init_control {
+ /* IN parameters. */
+ uint64_t control_gfn;
+ uint32_t offset;
+ uint32_t vcpu;
+ /* OUT parameters. */
+ uint8_t link_bits;
+ uint8_t _pad[7];
+};
+typedef struct evtchn_init_control evtchn_init_control_t;
+
+/*
+ * EVTCHNOP_expand_array: add an additional page to the event array.
+ */
+struct evtchn_expand_array {
+ /* IN parameters. */
+ uint64_t array_gfn;
+};
+typedef struct evtchn_expand_array evtchn_expand_array_t;
+
+/*
+ * EVTCHNOP_set_priority: set the priority for an event channel.
+ */
+struct evtchn_set_priority {
+ /* IN parameters. */
+ uint32_t port;
+ uint32_t priority;
+};
+typedef struct evtchn_set_priority evtchn_set_priority_t;
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_event_channel_op_compat(struct evtchn_op *op)
+ * `
+ * Superceded by new event_channel_op() hypercall since 0x00030202.
+ */
+struct evtchn_op {
+ uint32_t cmd; /* enum event_channel_op */
+ union {
+ struct evtchn_alloc_unbound alloc_unbound;
+ struct evtchn_bind_interdomain bind_interdomain;
+ struct evtchn_bind_virq bind_virq;
+ struct evtchn_bind_pirq bind_pirq;
+ struct evtchn_bind_ipi bind_ipi;
+ struct evtchn_close close;
+ struct evtchn_send send;
+ struct evtchn_status status;
+ struct evtchn_bind_vcpu bind_vcpu;
+ struct evtchn_unmask unmask;
+ } u;
+};
+typedef struct evtchn_op evtchn_op_t;
+DEFINE_XEN_GUEST_HANDLE(evtchn_op_t);
+
+/*
+ * 2-level ABI
+ */
+
+#define EVTCHN_2L_NR_CHANNELS (sizeof(xen_ulong_t) * sizeof(xen_ulong_t) * 64)
+
+/*
+ * FIFO ABI
+ */
+
+/* Events may have priorities from 0 (highest) to 15 (lowest). */
+#define EVTCHN_FIFO_PRIORITY_MAX 0
+#define EVTCHN_FIFO_PRIORITY_DEFAULT 7
+#define EVTCHN_FIFO_PRIORITY_MIN 15
+
+#define EVTCHN_FIFO_MAX_QUEUES (EVTCHN_FIFO_PRIORITY_MIN + 1)
+
+typedef uint32_t event_word_t;
+
+#define EVTCHN_FIFO_PENDING 31
+#define EVTCHN_FIFO_MASKED 30
+#define EVTCHN_FIFO_LINKED 29
+#define EVTCHN_FIFO_BUSY 28
+
+#define EVTCHN_FIFO_LINK_BITS 17
+#define EVTCHN_FIFO_LINK_MASK ((1 << EVTCHN_FIFO_LINK_BITS) - 1)
+
+#define EVTCHN_FIFO_NR_CHANNELS (1 << EVTCHN_FIFO_LINK_BITS)
+
+struct evtchn_fifo_control_block {
+ uint32_t ready;
+ uint32_t _rsvd;
+ uint32_t head[EVTCHN_FIFO_MAX_QUEUES];
+};
+typedef struct evtchn_fifo_control_block evtchn_fifo_control_block_t;
+
+#endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * features.h
+ *
+ * Feature flags, reported by XENVER_get_features.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2006, Keir Fraser <keir@xensource.com>
+ */
+
+#ifndef __XEN_PUBLIC_FEATURES_H__
+#define __XEN_PUBLIC_FEATURES_H__
+
+/*
+ * `incontents 200 elfnotes_features XEN_ELFNOTE_FEATURES
+ *
+ * The list of all the features the guest supports. They are set by
+ * parsing the XEN_ELFNOTE_FEATURES and XEN_ELFNOTE_SUPPORTED_FEATURES
+ * string. The format is the feature names (as given here without the
+ * "XENFEAT_" prefix) separated by '|' characters.
+ * If a feature is required for the kernel to function then the feature name
+ * must be preceded by a '!' character.
+ *
+ * Note that if XEN_ELFNOTE_SUPPORTED_FEATURES is used, then in the
+ * XENFEAT_dom0 MUST be set if the guest is to be booted as dom0,
+ */
+
+/*
+ * If set, the guest does not need to write-protect its pagetables, and can
+ * update them via direct writes.
+ */
+#define XENFEAT_writable_page_tables 0
+
+/*
+ * If set, the guest does not need to write-protect its segment descriptor
+ * tables, and can update them via direct writes.
+ */
+#define XENFEAT_writable_descriptor_tables 1
+
+/*
+ * If set, translation between the guest's 'pseudo-physical' address space
+ * and the host's machine address space are handled by the hypervisor. In this
+ * mode the guest does not need to perform phys-to/from-machine translations
+ * when performing page table operations.
+ */
+#define XENFEAT_auto_translated_physmap 2
+
+/* If set, the guest is running in supervisor mode (e.g., x86 ring 0). */
+#define XENFEAT_supervisor_mode_kernel 3
+
+/*
+ * If set, the guest does not need to allocate x86 PAE page directories
+ * below 4GB. This flag is usually implied by auto_translated_physmap.
+ */
+#define XENFEAT_pae_pgdir_above_4gb 4
+
+/* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */
+#define XENFEAT_mmu_pt_update_preserve_ad 5
+
+/* x86: Does this Xen host support the MMU_{CLEAR,COPY}_PAGE hypercall? */
+#define XENFEAT_highmem_assist 6
+
+/*
+ * If set, GNTTABOP_map_grant_ref honors flags to be placed into guest kernel
+ * available pte bits.
+ */
+#define XENFEAT_gnttab_map_avail_bits 7
+
+/* x86: Does this Xen host support the HVM callback vector type? */
+#define XENFEAT_hvm_callback_vector 8
+
+/* x86: pvclock algorithm is safe to use on HVM */
+#define XENFEAT_hvm_safe_pvclock 9
+
+/* x86: pirq can be used by HVM guests */
+#define XENFEAT_hvm_pirqs 10
+
+/* operation as Dom0 is supported */
+#define XENFEAT_dom0 11
+
+/* Xen also maps grant references at pfn = mfn.
+ * This feature flag is deprecated and should not be used.
+#define XENFEAT_grant_map_identity 12
+ */
+
+#define XENFEAT_NR_SUBMAPS 1
+
+#endif /* __XEN_PUBLIC_FEATURES_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * gcov.h
+ *
+ * Coverage structures exported by Xen.
+ * Structure is different from Gcc one.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2013, Citrix Systems R&D Ltd.
+ */
+
+#ifndef __XEN_PUBLIC_GCOV_H__
+#define __XEN_PUBLIC_GCOV_H__ __XEN_PUBLIC_GCOV_H__
+
+#define XENCOV_COUNTERS 5
+#define XENCOV_TAG_BASE 0x58544300u
+#define XENCOV_TAG_FILE (XENCOV_TAG_BASE+0x46u)
+#define XENCOV_TAG_FUNC (XENCOV_TAG_BASE+0x66u)
+#define XENCOV_TAG_COUNTER(n) (XENCOV_TAG_BASE+0x30u+((n)&0xfu))
+#define XENCOV_TAG_END (XENCOV_TAG_BASE+0x2eu)
+#define XENCOV_IS_TAG_COUNTER(n) \
+ ((n) >= XENCOV_TAG_COUNTER(0) && (n) < XENCOV_TAG_COUNTER(XENCOV_COUNTERS))
+#define XENCOV_COUNTER_NUM(n) ((n)-XENCOV_TAG_COUNTER(0))
+
+/*
+ * The main structure for the blob is
+ * BLOB := FILE.. END
+ * FILE := TAG_FILE VERSION STAMP FILENAME COUNTERS FUNCTIONS
+ * FILENAME := LEN characters
+ * characters are padded to 32 bit
+ * LEN := 32 bit value
+ * COUNTERS := TAG_COUNTER(n) NUM COUNTER..
+ * NUM := 32 bit valie
+ * COUNTER := 64 bit value
+ * FUNCTIONS := TAG_FUNC NUM FUNCTION..
+ * FUNCTION := IDENT CHECKSUM NUM_COUNTERS
+ *
+ * All tagged structures are aligned to 8 bytes
+ */
+
+/**
+ * File information
+ * Prefixed with XENCOV_TAG_FILE and a string with filename
+ * Aligned to 8 bytes
+ */
+struct xencov_file
+{
+ uint32_t tag; /* XENCOV_TAG_FILE */
+ uint32_t version;
+ uint32_t stamp;
+ uint32_t fn_len;
+ char filename[1];
+};
+
+
+/**
+ * Counters information
+ * Prefixed with XENCOV_TAG_COUNTER(n) where n is 0..(XENCOV_COUNTERS-1)
+ * Aligned to 8 bytes
+ */
+struct xencov_counter
+{
+ uint32_t tag; /* XENCOV_TAG_COUNTER(n) */
+ uint32_t num;
+ uint64_t values[1];
+};
+
+/**
+ * Information for each function
+ * Number of counter is equal to the number of counter structures got before
+ */
+struct xencov_function
+{
+ uint32_t ident;
+ uint32_t checksum;
+ uint32_t num_counters[1];
+};
+
+/**
+ * Information for all functions
+ * Aligned to 8 bytes
+ */
+struct xencov_functions
+{
+ uint32_t tag; /* XENCOV_TAG_FUNC */
+ uint32_t num;
+ struct xencov_function xencov_function[1];
+};
+
+/**
+ * Terminator
+ */
+struct xencov_end
+{
+ uint32_t tag; /* XENCOV_TAG_END */
+};
+
+#endif /* __XEN_PUBLIC_GCOV_H__ */
+
--- /dev/null
+/******************************************************************************
+ * grant_table.h
+ *
+ * Interface for granting foreign access to page frames, and receiving
+ * page-ownership transfers.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#ifndef __XEN_PUBLIC_GRANT_TABLE_H__
+#define __XEN_PUBLIC_GRANT_TABLE_H__
+
+#include "xen.h"
+
+/*
+ * `incontents 150 gnttab Grant Tables
+ *
+ * Xen's grant tables provide a generic mechanism to memory sharing
+ * between domains. This shared memory interface underpins the split
+ * device drivers for block and network IO.
+ *
+ * Each domain has its own grant table. This is a data structure that
+ * is shared with Xen; it allows the domain to tell Xen what kind of
+ * permissions other domains have on its pages. Entries in the grant
+ * table are identified by grant references. A grant reference is an
+ * integer, which indexes into the grant table. It acts as a
+ * capability which the grantee can use to perform operations on the
+ * granter’s memory.
+ *
+ * This capability-based system allows shared-memory communications
+ * between unprivileged domains. A grant reference also encapsulates
+ * the details of a shared page, removing the need for a domain to
+ * know the real machine address of a page it is sharing. This makes
+ * it possible to share memory correctly with domains running in
+ * fully virtualised memory.
+ */
+
+/***********************************
+ * GRANT TABLE REPRESENTATION
+ */
+
+/* Some rough guidelines on accessing and updating grant-table entries
+ * in a concurrency-safe manner. For more information, Linux contains a
+ * reference implementation for guest OSes (drivers/xen/grant_table.c, see
+ * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/xen/grant-table.c;hb=HEAD
+ *
+ * NB. WMB is a no-op on current-generation x86 processors. However, a
+ * compiler barrier will still be required.
+ *
+ * Introducing a valid entry into the grant table:
+ * 1. Write ent->domid.
+ * 2. Write ent->frame:
+ * GTF_permit_access: Frame to which access is permitted.
+ * GTF_accept_transfer: Pseudo-phys frame slot being filled by new
+ * frame, or zero if none.
+ * 3. Write memory barrier (WMB).
+ * 4. Write ent->flags, inc. valid type.
+ *
+ * Invalidating an unused GTF_permit_access entry:
+ * 1. flags = ent->flags.
+ * 2. Observe that !(flags & (GTF_reading|GTF_writing)).
+ * 3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
+ * NB. No need for WMB as reuse of entry is control-dependent on success of
+ * step 3, and all architectures guarantee ordering of ctrl-dep writes.
+ *
+ * Invalidating an in-use GTF_permit_access entry:
+ * This cannot be done directly. Request assistance from the domain controller
+ * which can set a timeout on the use of a grant entry and take necessary
+ * action. (NB. This is not yet implemented!).
+ *
+ * Invalidating an unused GTF_accept_transfer entry:
+ * 1. flags = ent->flags.
+ * 2. Observe that !(flags & GTF_transfer_committed). [*]
+ * 3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
+ * NB. No need for WMB as reuse of entry is control-dependent on success of
+ * step 3, and all architectures guarantee ordering of ctrl-dep writes.
+ * [*] If GTF_transfer_committed is set then the grant entry is 'committed'.
+ * The guest must /not/ modify the grant entry until the address of the
+ * transferred frame is written. It is safe for the guest to spin waiting
+ * for this to occur (detect by observing GTF_transfer_completed in
+ * ent->flags).
+ *
+ * Invalidating a committed GTF_accept_transfer entry:
+ * 1. Wait for (ent->flags & GTF_transfer_completed).
+ *
+ * Changing a GTF_permit_access from writable to read-only:
+ * Use SMP-safe CMPXCHG to set GTF_readonly, while checking !GTF_writing.
+ *
+ * Changing a GTF_permit_access from read-only to writable:
+ * Use SMP-safe bit-setting instruction.
+ */
+
+/*
+ * Reference to a grant entry in a specified domain's grant table.
+ */
+typedef uint32_t grant_ref_t;
+
+/*
+ * A grant table comprises a packed array of grant entries in one or more
+ * page frames shared between Xen and a guest.
+ * [XEN]: This field is written by Xen and read by the sharing guest.
+ * [GST]: This field is written by the guest and read by Xen.
+ */
+
+/*
+ * Version 1 of the grant table entry structure is maintained purely
+ * for backwards compatibility. New guests should use version 2.
+ */
+#if __XEN_INTERFACE_VERSION__ < 0x0003020a
+#define grant_entry_v1 grant_entry
+#define grant_entry_v1_t grant_entry_t
+#endif
+struct grant_entry_v1 {
+ /* GTF_xxx: various type and flag information. [XEN,GST] */
+ uint16_t flags;
+ /* The domain being granted foreign privileges. [GST] */
+ domid_t domid;
+ /*
+ * GTF_permit_access: Frame that @domid is allowed to map and access. [GST]
+ * GTF_accept_transfer: Frame whose ownership transferred by @domid. [XEN]
+ */
+ uint32_t frame;
+};
+typedef struct grant_entry_v1 grant_entry_v1_t;
+
+/* The first few grant table entries will be preserved across grant table
+ * version changes and may be pre-populated at domain creation by tools.
+ */
+#define GNTTAB_NR_RESERVED_ENTRIES 8
+#define GNTTAB_RESERVED_CONSOLE 0
+#define GNTTAB_RESERVED_XENSTORE 1
+
+/*
+ * Type of grant entry.
+ * GTF_invalid: This grant entry grants no privileges.
+ * GTF_permit_access: Allow @domid to map/access @frame.
+ * GTF_accept_transfer: Allow @domid to transfer ownership of one page frame
+ * to this guest. Xen writes the page number to @frame.
+ * GTF_transitive: Allow @domid to transitively access a subrange of
+ * @trans_grant in @trans_domid. No mappings are allowed.
+ */
+#define GTF_invalid (0U<<0)
+#define GTF_permit_access (1U<<0)
+#define GTF_accept_transfer (2U<<0)
+#define GTF_transitive (3U<<0)
+#define GTF_type_mask (3U<<0)
+
+/*
+ * Subflags for GTF_permit_access.
+ * GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST]
+ * GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN]
+ * GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN]
+ * GTF_PAT, GTF_PWT, GTF_PCD: (x86) cache attribute flags for the grant [GST]
+ * GTF_sub_page: Grant access to only a subrange of the page. @domid
+ * will only be allowed to copy from the grant, and not
+ * map it. [GST]
+ */
+#define _GTF_readonly (2)
+#define GTF_readonly (1U<<_GTF_readonly)
+#define _GTF_reading (3)
+#define GTF_reading (1U<<_GTF_reading)
+#define _GTF_writing (4)
+#define GTF_writing (1U<<_GTF_writing)
+#define _GTF_PWT (5)
+#define GTF_PWT (1U<<_GTF_PWT)
+#define _GTF_PCD (6)
+#define GTF_PCD (1U<<_GTF_PCD)
+#define _GTF_PAT (7)
+#define GTF_PAT (1U<<_GTF_PAT)
+#define _GTF_sub_page (8)
+#define GTF_sub_page (1U<<_GTF_sub_page)
+
+/*
+ * Subflags for GTF_accept_transfer:
+ * GTF_transfer_committed: Xen sets this flag to indicate that it is committed
+ * to transferring ownership of a page frame. When a guest sees this flag
+ * it must /not/ modify the grant entry until GTF_transfer_completed is
+ * set by Xen.
+ * GTF_transfer_completed: It is safe for the guest to spin-wait on this flag
+ * after reading GTF_transfer_committed. Xen will always write the frame
+ * address, followed by ORing this flag, in a timely manner.
+ */
+#define _GTF_transfer_committed (2)
+#define GTF_transfer_committed (1U<<_GTF_transfer_committed)
+#define _GTF_transfer_completed (3)
+#define GTF_transfer_completed (1U<<_GTF_transfer_completed)
+
+/*
+ * Version 2 grant table entries. These fulfil the same role as
+ * version 1 entries, but can represent more complicated operations.
+ * Any given domain will have either a version 1 or a version 2 table,
+ * and every entry in the table will be the same version.
+ *
+ * The interface by which domains use grant references does not depend
+ * on the grant table version in use by the other domain.
+ */
+#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
+/*
+ * Version 1 and version 2 grant entries share a common prefix. The
+ * fields of the prefix are documented as part of struct
+ * grant_entry_v1.
+ */
+struct grant_entry_header {
+ uint16_t flags;
+ domid_t domid;
+};
+typedef struct grant_entry_header grant_entry_header_t;
+
+/*
+ * Version 2 of the grant entry structure.
+ */
+union grant_entry_v2 {
+ grant_entry_header_t hdr;
+
+ /*
+ * This member is used for V1-style full page grants, where either:
+ *
+ * -- hdr.type is GTF_accept_transfer, or
+ * -- hdr.type is GTF_permit_access and GTF_sub_page is not set.
+ *
+ * In that case, the frame field has the same semantics as the
+ * field of the same name in the V1 entry structure.
+ */
+ struct {
+ grant_entry_header_t hdr;
+ uint32_t pad0;
+ uint64_t frame;
+ } full_page;
+
+ /*
+ * If the grant type is GTF_grant_access and GTF_sub_page is set,
+ * @domid is allowed to access bytes [@page_off,@page_off+@length)
+ * in frame @frame.
+ */
+ struct {
+ grant_entry_header_t hdr;
+ uint16_t page_off;
+ uint16_t length;
+ uint64_t frame;
+ } sub_page;
+
+ /*
+ * If the grant is GTF_transitive, @domid is allowed to use the
+ * grant @gref in domain @trans_domid, as if it was the local
+ * domain. Obviously, the transitive access must be compatible
+ * with the original grant.
+ *
+ * The current version of Xen does not allow transitive grants
+ * to be mapped.
+ */
+ struct {
+ grant_entry_header_t hdr;
+ domid_t trans_domid;
+ uint16_t pad0;
+ grant_ref_t gref;
+ } transitive;
+
+ uint32_t __spacer[4]; /* Pad to a power of two */
+};
+typedef union grant_entry_v2 grant_entry_v2_t;
+
+typedef uint16_t grant_status_t;
+
+#endif /* __XEN_INTERFACE_VERSION__ */
+
+/***********************************
+ * GRANT TABLE QUERIES AND USES
+ */
+
+/* ` enum neg_errnoval
+ * ` HYPERVISOR_grant_table_op(enum grant_table_op cmd,
+ * ` void *args,
+ * ` unsigned int count)
+ * `
+ *
+ * @args points to an array of a per-command data structure. The array
+ * has @count members
+ */
+
+/* ` enum grant_table_op { // GNTTABOP_* => struct gnttab_* */
+#define GNTTABOP_map_grant_ref 0
+#define GNTTABOP_unmap_grant_ref 1
+#define GNTTABOP_setup_table 2
+#define GNTTABOP_dump_table 3
+#define GNTTABOP_transfer 4
+#define GNTTABOP_copy 5
+#define GNTTABOP_query_size 6
+#define GNTTABOP_unmap_and_replace 7
+#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
+#define GNTTABOP_set_version 8
+#define GNTTABOP_get_status_frames 9
+#define GNTTABOP_get_version 10
+#define GNTTABOP_swap_grant_ref 11
+#define GNTTABOP_cache_flush 12
+#endif /* __XEN_INTERFACE_VERSION__ */
+/* ` } */
+
+/*
+ * Handle to track a mapping created via a grant reference.
+ */
+typedef uint32_t grant_handle_t;
+
+/*
+ * GNTTABOP_map_grant_ref: Map the grant entry (<dom>,<ref>) for access
+ * by devices and/or host CPUs. If successful, <handle> is a tracking number
+ * that must be presented later to destroy the mapping(s). On error, <handle>
+ * is a negative status code.
+ * NOTES:
+ * 1. If GNTMAP_device_map is specified then <dev_bus_addr> is the address
+ * via which I/O devices may access the granted frame.
+ * 2. If GNTMAP_host_map is specified then a mapping will be added at
+ * either a host virtual address in the current address space, or at
+ * a PTE at the specified machine address. The type of mapping to
+ * perform is selected through the GNTMAP_contains_pte flag, and the
+ * address is specified in <host_addr>.
+ * 3. Mappings should only be destroyed via GNTTABOP_unmap_grant_ref. If a
+ * host mapping is destroyed by other means then it is *NOT* guaranteed
+ * to be accounted to the correct grant reference!
+ */
+struct gnttab_map_grant_ref {
+ /* IN parameters. */
+ uint64_t host_addr;
+ uint32_t flags; /* GNTMAP_* */
+ grant_ref_t ref;
+ domid_t dom;
+ /* OUT parameters. */
+ int16_t status; /* => enum grant_status */
+ grant_handle_t handle;
+ uint64_t dev_bus_addr;
+};
+typedef struct gnttab_map_grant_ref gnttab_map_grant_ref_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_map_grant_ref_t);
+
+/*
+ * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
+ * tracked by <handle>. If <host_addr> or <dev_bus_addr> is zero, that
+ * field is ignored. If non-zero, they must refer to a device/host mapping
+ * that is tracked by <handle>
+ * NOTES:
+ * 1. The call may fail in an undefined manner if either mapping is not
+ * tracked by <handle>.
+ * 3. After executing a batch of unmaps, it is guaranteed that no stale
+ * mappings will remain in the device or host TLBs.
+ */
+struct gnttab_unmap_grant_ref {
+ /* IN parameters. */
+ uint64_t host_addr;
+ uint64_t dev_bus_addr;
+ grant_handle_t handle;
+ /* OUT parameters. */
+ int16_t status; /* => enum grant_status */
+};
+typedef struct gnttab_unmap_grant_ref gnttab_unmap_grant_ref_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_grant_ref_t);
+
+/*
+ * GNTTABOP_setup_table: Set up a grant table for <dom> comprising at least
+ * <nr_frames> pages. The frame addresses are written to the <frame_list>.
+ * Only <nr_frames> addresses are written, even if the table is larger.
+ * NOTES:
+ * 1. <dom> may be specified as DOMID_SELF.
+ * 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
+ * 3. Xen may not support more than a single grant-table page per domain.
+ */
+struct gnttab_setup_table {
+ /* IN parameters. */
+ domid_t dom;
+ uint32_t nr_frames;
+ /* OUT parameters. */
+ int16_t status; /* => enum grant_status */
+#if __XEN_INTERFACE_VERSION__ < 0x00040300
+ XEN_GUEST_HANDLE(ulong) frame_list;
+#else
+ XEN_GUEST_HANDLE(xen_pfn_t) frame_list;
+#endif
+};
+typedef struct gnttab_setup_table gnttab_setup_table_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_setup_table_t);
+
+/*
+ * GNTTABOP_dump_table: Dump the contents of the grant table to the
+ * xen console. Debugging use only.
+ */
+struct gnttab_dump_table {
+ /* IN parameters. */
+ domid_t dom;
+ /* OUT parameters. */
+ int16_t status; /* => enum grant_status */
+};
+typedef struct gnttab_dump_table gnttab_dump_table_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_dump_table_t);
+
+/*
+ * GNTTABOP_transfer_grant_ref: Transfer <frame> to a foreign domain. The
+ * foreign domain has previously registered its interest in the transfer via
+ * <domid, ref>.
+ *
+ * Note that, even if the transfer fails, the specified page no longer belongs
+ * to the calling domain *unless* the error is GNTST_bad_page.
+ */
+struct gnttab_transfer {
+ /* IN parameters. */
+ xen_pfn_t mfn;
+ domid_t domid;
+ grant_ref_t ref;
+ /* OUT parameters. */
+ int16_t status;
+};
+typedef struct gnttab_transfer gnttab_transfer_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_transfer_t);
+
+
+/*
+ * GNTTABOP_copy: Hypervisor based copy
+ * source and destinations can be eithers MFNs or, for foreign domains,
+ * grant references. the foreign domain has to grant read/write access
+ * in its grant table.
+ *
+ * The flags specify what type source and destinations are (either MFN
+ * or grant reference).
+ *
+ * Note that this can also be used to copy data between two domains
+ * via a third party if the source and destination domains had previously
+ * grant appropriate access to their pages to the third party.
+ *
+ * source_offset specifies an offset in the source frame, dest_offset
+ * the offset in the target frame and len specifies the number of
+ * bytes to be copied.
+ */
+
+#define _GNTCOPY_source_gref (0)
+#define GNTCOPY_source_gref (1<<_GNTCOPY_source_gref)
+#define _GNTCOPY_dest_gref (1)
+#define GNTCOPY_dest_gref (1<<_GNTCOPY_dest_gref)
+
+struct gnttab_copy {
+ /* IN parameters. */
+ struct {
+ union {
+ grant_ref_t ref;
+ xen_pfn_t gmfn;
+ } u;
+ domid_t domid;
+ uint16_t offset;
+ } source, dest;
+ uint16_t len;
+ uint16_t flags; /* GNTCOPY_* */
+ /* OUT parameters. */
+ int16_t status;
+};
+typedef struct gnttab_copy gnttab_copy_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_copy_t);
+
+/*
+ * GNTTABOP_query_size: Query the current and maximum sizes of the shared
+ * grant table.
+ * NOTES:
+ * 1. <dom> may be specified as DOMID_SELF.
+ * 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
+ */
+struct gnttab_query_size {
+ /* IN parameters. */
+ domid_t dom;
+ /* OUT parameters. */
+ uint32_t nr_frames;
+ uint32_t max_nr_frames;
+ int16_t status; /* => enum grant_status */
+};
+typedef struct gnttab_query_size gnttab_query_size_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_query_size_t);
+
+/*
+ * GNTTABOP_unmap_and_replace: Destroy one or more grant-reference mappings
+ * tracked by <handle> but atomically replace the page table entry with one
+ * pointing to the machine address under <new_addr>. <new_addr> will be
+ * redirected to the null entry.
+ * NOTES:
+ * 1. The call may fail in an undefined manner if either mapping is not
+ * tracked by <handle>.
+ * 2. After executing a batch of unmaps, it is guaranteed that no stale
+ * mappings will remain in the device or host TLBs.
+ */
+struct gnttab_unmap_and_replace {
+ /* IN parameters. */
+ uint64_t host_addr;
+ uint64_t new_addr;
+ grant_handle_t handle;
+ /* OUT parameters. */
+ int16_t status; /* => enum grant_status */
+};
+typedef struct gnttab_unmap_and_replace gnttab_unmap_and_replace_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_and_replace_t);
+
+#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
+/*
+ * GNTTABOP_set_version: Request a particular version of the grant
+ * table shared table structure. This operation can only be performed
+ * once in any given domain. It must be performed before any grants
+ * are activated; otherwise, the domain will be stuck with version 1.
+ * The only defined versions are 1 and 2.
+ */
+struct gnttab_set_version {
+ /* IN/OUT parameters */
+ uint32_t version;
+};
+typedef struct gnttab_set_version gnttab_set_version_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_set_version_t);
+
+
+/*
+ * GNTTABOP_get_status_frames: Get the list of frames used to store grant
+ * status for <dom>. In grant format version 2, the status is separated
+ * from the other shared grant fields to allow more efficient synchronization
+ * using barriers instead of atomic cmpexch operations.
+ * <nr_frames> specify the size of vector <frame_list>.
+ * The frame addresses are returned in the <frame_list>.
+ * Only <nr_frames> addresses are returned, even if the table is larger.
+ * NOTES:
+ * 1. <dom> may be specified as DOMID_SELF.
+ * 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
+ */
+struct gnttab_get_status_frames {
+ /* IN parameters. */
+ uint32_t nr_frames;
+ domid_t dom;
+ /* OUT parameters. */
+ int16_t status; /* => enum grant_status */
+ XEN_GUEST_HANDLE(uint64_t) frame_list;
+};
+typedef struct gnttab_get_status_frames gnttab_get_status_frames_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_get_status_frames_t);
+
+/*
+ * GNTTABOP_get_version: Get the grant table version which is in
+ * effect for domain <dom>.
+ */
+struct gnttab_get_version {
+ /* IN parameters */
+ domid_t dom;
+ uint16_t pad;
+ /* OUT parameters */
+ uint32_t version;
+};
+typedef struct gnttab_get_version gnttab_get_version_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_get_version_t);
+
+/*
+ * GNTTABOP_swap_grant_ref: Swap the contents of two grant entries.
+ */
+struct gnttab_swap_grant_ref {
+ /* IN parameters */
+ grant_ref_t ref_a;
+ grant_ref_t ref_b;
+ /* OUT parameters */
+ int16_t status; /* => enum grant_status */
+};
+typedef struct gnttab_swap_grant_ref gnttab_swap_grant_ref_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t);
+
+/*
+ * Issue one or more cache maintenance operations on a portion of a
+ * page granted to the calling domain by a foreign domain.
+ */
+struct gnttab_cache_flush {
+ union {
+ uint64_t dev_bus_addr;
+ grant_ref_t ref;
+ } a;
+ uint16_t offset; /* offset from start of grant */
+ uint16_t length; /* size within the grant */
+#define GNTTAB_CACHE_CLEAN (1<<0)
+#define GNTTAB_CACHE_INVAL (1<<1)
+#define GNTTAB_CACHE_SOURCE_GREF (1<<31)
+ uint32_t op;
+};
+typedef struct gnttab_cache_flush gnttab_cache_flush_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_cache_flush_t);
+
+#endif /* __XEN_INTERFACE_VERSION__ */
+
+/*
+ * Bitfield values for gnttab_map_grant_ref.flags.
+ */
+ /* Map the grant entry for access by I/O devices. */
+#define _GNTMAP_device_map (0)
+#define GNTMAP_device_map (1<<_GNTMAP_device_map)
+ /* Map the grant entry for access by host CPUs. */
+#define _GNTMAP_host_map (1)
+#define GNTMAP_host_map (1<<_GNTMAP_host_map)
+ /* Accesses to the granted frame will be restricted to read-only access. */
+#define _GNTMAP_readonly (2)
+#define GNTMAP_readonly (1<<_GNTMAP_readonly)
+ /*
+ * GNTMAP_host_map subflag:
+ * 0 => The host mapping is usable only by the guest OS.
+ * 1 => The host mapping is usable by guest OS + current application.
+ */
+#define _GNTMAP_application_map (3)
+#define GNTMAP_application_map (1<<_GNTMAP_application_map)
+
+ /*
+ * GNTMAP_contains_pte subflag:
+ * 0 => This map request contains a host virtual address.
+ * 1 => This map request contains the machine addess of the PTE to update.
+ */
+#define _GNTMAP_contains_pte (4)
+#define GNTMAP_contains_pte (1<<_GNTMAP_contains_pte)
+
+#define _GNTMAP_can_fail (5)
+#define GNTMAP_can_fail (1<<_GNTMAP_can_fail)
+
+/*
+ * Bits to be placed in guest kernel available PTE bits (architecture
+ * dependent; only supported when XENFEAT_gnttab_map_avail_bits is set).
+ */
+#define _GNTMAP_guest_avail0 (16)
+#define GNTMAP_guest_avail_mask ((uint32_t)~0 << _GNTMAP_guest_avail0)
+
+/*
+ * Values for error status returns. All errors are -ve.
+ */
+/* ` enum grant_status { */
+#define GNTST_okay (0) /* Normal return. */
+#define GNTST_general_error (-1) /* General undefined error. */
+#define GNTST_bad_domain (-2) /* Unrecognsed domain id. */
+#define GNTST_bad_gntref (-3) /* Unrecognised or inappropriate gntref. */
+#define GNTST_bad_handle (-4) /* Unrecognised or inappropriate handle. */
+#define GNTST_bad_virt_addr (-5) /* Inappropriate virtual address to map. */
+#define GNTST_bad_dev_addr (-6) /* Inappropriate device address to unmap.*/
+#define GNTST_no_device_space (-7) /* Out of space in I/O MMU. */
+#define GNTST_permission_denied (-8) /* Not enough privilege for operation. */
+#define GNTST_bad_page (-9) /* Specified page was invalid for op. */
+#define GNTST_bad_copy_arg (-10) /* copy arguments cross page boundary. */
+#define GNTST_address_too_big (-11) /* transfer page address too large. */
+#define GNTST_eagain (-12) /* Operation not done; try again. */
+/* ` } */
+
+#define GNTTABOP_error_msgs { \
+ "okay", \
+ "undefined error", \
+ "unrecognised domain id", \
+ "invalid grant reference", \
+ "invalid mapping handle", \
+ "invalid virtual address", \
+ "invalid device address", \
+ "no spare translation slot in the I/O MMU", \
+ "permission denied", \
+ "bad page", \
+ "copy arguments cross page boundary", \
+ "page address size too large", \
+ "operation not done; try again" \
+}
+
+#endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PUBLIC_HVM_E820_H__
+#define __XEN_PUBLIC_HVM_E820_H__
+
+/* E820 location in HVM virtual address space. */
+#define HVM_E820_PAGE 0x00090000
+#define HVM_E820_NR_OFFSET 0x000001E8
+#define HVM_E820_OFFSET 0x000002D0
+
+#define HVM_BELOW_4G_RAM_END 0xF0000000
+#define HVM_BELOW_4G_MMIO_START HVM_BELOW_4G_RAM_END
+#define HVM_BELOW_4G_MMIO_LENGTH ((1ULL << 32) - HVM_BELOW_4G_MMIO_START)
+
+#endif /* __XEN_PUBLIC_HVM_E820_H__ */
--- /dev/null
+/******************************************************************************
+ * hvm/hvm_info_table.h
+ *
+ * HVM parameter and information table, written into guest memory map.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__
+#define __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__
+
+#define HVM_INFO_PFN 0x09F
+#define HVM_INFO_OFFSET 0x800
+#define HVM_INFO_PADDR ((HVM_INFO_PFN << 12) + HVM_INFO_OFFSET)
+
+/* Maximum we can support with current vLAPIC ID mapping. */
+#define HVM_MAX_VCPUS 128
+
+struct hvm_info_table {
+ char signature[8]; /* "HVM INFO" */
+ uint32_t length;
+ uint8_t checksum;
+
+ /* Should firmware build APIC descriptors (APIC MADT / MP BIOS)? */
+ uint8_t apic_mode;
+
+ /* How many CPUs does this domain have? */
+ uint32_t nr_vcpus;
+
+ /*
+ * MEMORY MAP provided by HVM domain builder.
+ * Notes:
+ * 1. page_to_phys(x) = x << 12
+ * 2. If a field is zero, the corresponding range does not exist.
+ */
+ /*
+ * 0x0 to page_to_phys(low_mem_pgend)-1:
+ * RAM below 4GB (except for VGA hole 0xA0000-0xBFFFF)
+ */
+ uint32_t low_mem_pgend;
+ /*
+ * page_to_phys(reserved_mem_pgstart) to 0xFFFFFFFF:
+ * Reserved for special memory mappings
+ */
+ uint32_t reserved_mem_pgstart;
+ /*
+ * 0x100000000 to page_to_phys(high_mem_pgend)-1:
+ * RAM above 4GB
+ */
+ uint32_t high_mem_pgend;
+
+ /* Bitmap of which CPUs are online at boot time. */
+ uint8_t vcpu_online[(HVM_MAX_VCPUS + 7)/8];
+};
+
+#endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */
--- /dev/null
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PUBLIC_HVM_HVM_OP_H__
+#define __XEN_PUBLIC_HVM_HVM_OP_H__
+
+#include "../xen.h"
+#include "../trace.h"
+#include "../event_channel.h"
+
+/* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
+#define HVMOP_set_param 0
+#define HVMOP_get_param 1
+struct xen_hvm_param {
+ domid_t domid; /* IN */
+ uint32_t index; /* IN */
+ uint64_t value; /* IN/OUT */
+};
+typedef struct xen_hvm_param xen_hvm_param_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_param_t);
+
+/* Set the logical level of one of a domain's PCI INTx wires. */
+#define HVMOP_set_pci_intx_level 2
+struct xen_hvm_set_pci_intx_level {
+ /* Domain to be updated. */
+ domid_t domid;
+ /* PCI INTx identification in PCI topology (domain:bus:device:intx). */
+ uint8_t domain, bus, device, intx;
+ /* Assertion level (0 = unasserted, 1 = asserted). */
+ uint8_t level;
+};
+typedef struct xen_hvm_set_pci_intx_level xen_hvm_set_pci_intx_level_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_intx_level_t);
+
+/* Set the logical level of one of a domain's ISA IRQ wires. */
+#define HVMOP_set_isa_irq_level 3
+struct xen_hvm_set_isa_irq_level {
+ /* Domain to be updated. */
+ domid_t domid;
+ /* ISA device identification, by ISA IRQ (0-15). */
+ uint8_t isa_irq;
+ /* Assertion level (0 = unasserted, 1 = asserted). */
+ uint8_t level;
+};
+typedef struct xen_hvm_set_isa_irq_level xen_hvm_set_isa_irq_level_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_isa_irq_level_t);
+
+#define HVMOP_set_pci_link_route 4
+struct xen_hvm_set_pci_link_route {
+ /* Domain to be updated. */
+ domid_t domid;
+ /* PCI link identifier (0-3). */
+ uint8_t link;
+ /* ISA IRQ (1-15), or 0 (disable link). */
+ uint8_t isa_irq;
+};
+typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t);
+
+/* Flushes all VCPU TLBs: @arg must be NULL. */
+#define HVMOP_flush_tlbs 5
+
+typedef enum {
+ HVMMEM_ram_rw, /* Normal read/write guest RAM */
+ HVMMEM_ram_ro, /* Read-only; writes are discarded */
+ HVMMEM_mmio_dm, /* Reads and write go to the device model */
+ HVMMEM_mmio_write_dm /* Read-only; writes go to the device model */
+} hvmmem_type_t;
+
+/* Following tools-only interfaces may change in future. */
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+/* Track dirty VRAM. */
+#define HVMOP_track_dirty_vram 6
+struct xen_hvm_track_dirty_vram {
+ /* Domain to be tracked. */
+ domid_t domid;
+ /* Number of pages to track. */
+ uint32_t nr;
+ /* First pfn to track. */
+ uint64_aligned_t first_pfn;
+ /* OUT variable. */
+ /* Dirty bitmap buffer. */
+ XEN_GUEST_HANDLE_64(uint8) dirty_bitmap;
+};
+typedef struct xen_hvm_track_dirty_vram xen_hvm_track_dirty_vram_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_track_dirty_vram_t);
+
+/* Notify that some pages got modified by the Device Model. */
+#define HVMOP_modified_memory 7
+struct xen_hvm_modified_memory {
+ /* Domain to be updated. */
+ domid_t domid;
+ /* Number of pages. */
+ uint32_t nr;
+ /* First pfn. */
+ uint64_aligned_t first_pfn;
+};
+typedef struct xen_hvm_modified_memory xen_hvm_modified_memory_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_modified_memory_t);
+
+#define HVMOP_set_mem_type 8
+/* Notify that a region of memory is to be treated in a specific way. */
+struct xen_hvm_set_mem_type {
+ /* Domain to be updated. */
+ domid_t domid;
+ /* Memory type */
+ uint16_t hvmmem_type;
+ /* Number of pages. */
+ uint32_t nr;
+ /* First pfn. */
+ uint64_aligned_t first_pfn;
+};
+typedef struct xen_hvm_set_mem_type xen_hvm_set_mem_type_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_mem_type_t);
+
+#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+
+/* Hint from PV drivers for pagetable destruction. */
+#define HVMOP_pagetable_dying 9
+struct xen_hvm_pagetable_dying {
+ /* Domain with a pagetable about to be destroyed. */
+ domid_t domid;
+ uint16_t pad[3]; /* align next field on 8-byte boundary */
+ /* guest physical address of the toplevel pagetable dying */
+ uint64_t gpa;
+};
+typedef struct xen_hvm_pagetable_dying xen_hvm_pagetable_dying_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_pagetable_dying_t);
+
+/* Get the current Xen time, in nanoseconds since system boot. */
+#define HVMOP_get_time 10
+struct xen_hvm_get_time {
+ uint64_t now; /* OUT */
+};
+typedef struct xen_hvm_get_time xen_hvm_get_time_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_time_t);
+
+#define HVMOP_xentrace 11
+struct xen_hvm_xentrace {
+ uint16_t event, extra_bytes;
+ uint8_t extra[TRACE_EXTRA_MAX * sizeof(uint32_t)];
+};
+typedef struct xen_hvm_xentrace xen_hvm_xentrace_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_xentrace_t);
+
+/* Following tools-only interfaces may change in future. */
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+/* Deprecated by XENMEM_access_op_set_access */
+#define HVMOP_set_mem_access 12
+
+/* Deprecated by XENMEM_access_op_get_access */
+#define HVMOP_get_mem_access 13
+
+#define HVMOP_inject_trap 14
+/* Inject a trap into a VCPU, which will get taken up on the next
+ * scheduling of it. Note that the caller should know enough of the
+ * state of the CPU before injecting, to know what the effect of
+ * injecting the trap will be.
+ */
+struct xen_hvm_inject_trap {
+ /* Domain to be queried. */
+ domid_t domid;
+ /* VCPU */
+ uint32_t vcpuid;
+ /* Vector number */
+ uint32_t vector;
+ /* Trap type (HVMOP_TRAP_*) */
+ uint32_t type;
+/* NB. This enumeration precisely matches hvm.h:X86_EVENTTYPE_* */
+# define HVMOP_TRAP_ext_int 0 /* external interrupt */
+# define HVMOP_TRAP_nmi 2 /* nmi */
+# define HVMOP_TRAP_hw_exc 3 /* hardware exception */
+# define HVMOP_TRAP_sw_int 4 /* software interrupt (CD nn) */
+# define HVMOP_TRAP_pri_sw_exc 5 /* ICEBP (F1) */
+# define HVMOP_TRAP_sw_exc 6 /* INT3 (CC), INTO (CE) */
+ /* Error code, or ~0u to skip */
+ uint32_t error_code;
+ /* Intruction length */
+ uint32_t insn_len;
+ /* CR2 for page faults */
+ uint64_aligned_t cr2;
+};
+typedef struct xen_hvm_inject_trap xen_hvm_inject_trap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_inject_trap_t);
+
+#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+
+#define HVMOP_get_mem_type 15
+/* Return hvmmem_type_t for the specified pfn. */
+struct xen_hvm_get_mem_type {
+ /* Domain to be queried. */
+ domid_t domid;
+ /* OUT variable. */
+ uint16_t mem_type;
+ uint16_t pad[2]; /* align next field on 8-byte boundary */
+ /* IN variable. */
+ uint64_t pfn;
+};
+typedef struct xen_hvm_get_mem_type xen_hvm_get_mem_type_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_mem_type_t);
+
+/* Following tools-only interfaces may change in future. */
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+/* MSI injection for emulated devices */
+#define HVMOP_inject_msi 16
+struct xen_hvm_inject_msi {
+ /* Domain to be injected */
+ domid_t domid;
+ /* Data -- lower 32 bits */
+ uint32_t data;
+ /* Address (0xfeexxxxx) */
+ uint64_t addr;
+};
+typedef struct xen_hvm_inject_msi xen_hvm_inject_msi_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_inject_msi_t);
+
+/*
+ * IOREQ Servers
+ *
+ * The interface between an I/O emulator an Xen is called an IOREQ Server.
+ * A domain supports a single 'legacy' IOREQ Server which is instantiated if
+ * parameter...
+ *
+ * HVM_PARAM_IOREQ_PFN is read (to get the gmfn containing the synchronous
+ * ioreq structures), or...
+ * HVM_PARAM_BUFIOREQ_PFN is read (to get the gmfn containing the buffered
+ * ioreq ring), or...
+ * HVM_PARAM_BUFIOREQ_EVTCHN is read (to get the event channel that Xen uses
+ * to request buffered I/O emulation).
+ *
+ * The following hypercalls facilitate the creation of IOREQ Servers for
+ * 'secondary' emulators which are invoked to implement port I/O, memory, or
+ * PCI config space ranges which they explicitly register.
+ */
+
+typedef uint16_t ioservid_t;
+
+/*
+ * HVMOP_create_ioreq_server: Instantiate a new IOREQ Server for a secondary
+ * emulator servicing domain <domid>.
+ *
+ * The <id> handed back is unique for <domid>. If <handle_bufioreq> is zero
+ * the buffered ioreq ring will not be allocated and hence all emulation
+ * requestes to this server will be synchronous.
+ */
+#define HVMOP_create_ioreq_server 17
+struct xen_hvm_create_ioreq_server {
+ domid_t domid; /* IN - domain to be serviced */
+ uint8_t handle_bufioreq; /* IN - should server handle buffered ioreqs */
+ ioservid_t id; /* OUT - server id */
+};
+typedef struct xen_hvm_create_ioreq_server xen_hvm_create_ioreq_server_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_create_ioreq_server_t);
+
+/*
+ * HVMOP_get_ioreq_server_info: Get all the information necessary to access
+ * IOREQ Server <id>.
+ *
+ * The emulator needs to map the synchronous ioreq structures and buffered
+ * ioreq ring (if it exists) that Xen uses to request emulation. These are
+ * hosted in domain <domid>'s gmfns <ioreq_pfn> and <bufioreq_pfn>
+ * respectively. In addition, if the IOREQ Server is handling buffered
+ * emulation requests, the emulator needs to bind to event channel
+ * <bufioreq_port> to listen for them. (The event channels used for
+ * synchronous emulation requests are specified in the per-CPU ioreq
+ * structures in <ioreq_pfn>).
+ * If the IOREQ Server is not handling buffered emulation requests then the
+ * values handed back in <bufioreq_pfn> and <bufioreq_port> will both be 0.
+ */
+#define HVMOP_get_ioreq_server_info 18
+struct xen_hvm_get_ioreq_server_info {
+ domid_t domid; /* IN - domain to be serviced */
+ ioservid_t id; /* IN - server id */
+ evtchn_port_t bufioreq_port; /* OUT - buffered ioreq port */
+ uint64_aligned_t ioreq_pfn; /* OUT - sync ioreq pfn */
+ uint64_aligned_t bufioreq_pfn; /* OUT - buffered ioreq pfn */
+};
+typedef struct xen_hvm_get_ioreq_server_info xen_hvm_get_ioreq_server_info_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_ioreq_server_info_t);
+
+/*
+ * HVM_map_io_range_to_ioreq_server: Register an I/O range of domain <domid>
+ * for emulation by the client of IOREQ
+ * Server <id>
+ * HVM_unmap_io_range_from_ioreq_server: Deregister an I/O range of <domid>
+ * for emulation by the client of IOREQ
+ * Server <id>
+ *
+ * There are three types of I/O that can be emulated: port I/O, memory accesses
+ * and PCI config space accesses. The <type> field denotes which type of range
+ * the <start> and <end> (inclusive) fields are specifying.
+ * PCI config space ranges are specified by segment/bus/device/function values
+ * which should be encoded using the HVMOP_PCI_SBDF helper macro below.
+ *
+ * NOTE: unless an emulation request falls entirely within a range mapped
+ * by a secondary emulator, it will not be passed to that emulator.
+ */
+#define HVMOP_map_io_range_to_ioreq_server 19
+#define HVMOP_unmap_io_range_from_ioreq_server 20
+struct xen_hvm_io_range {
+ domid_t domid; /* IN - domain to be serviced */
+ ioservid_t id; /* IN - server id */
+ uint32_t type; /* IN - type of range */
+# define HVMOP_IO_RANGE_PORT 0 /* I/O port range */
+# define HVMOP_IO_RANGE_MEMORY 1 /* MMIO range */
+# define HVMOP_IO_RANGE_PCI 2 /* PCI segment/bus/dev/func range */
+ uint64_aligned_t start, end; /* IN - inclusive start and end of range */
+};
+typedef struct xen_hvm_io_range xen_hvm_io_range_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_io_range_t);
+
+#define HVMOP_PCI_SBDF(s,b,d,f) \
+ ((((s) & 0xffff) << 16) | \
+ (((b) & 0xff) << 8) | \
+ (((d) & 0x1f) << 3) | \
+ ((f) & 0x07))
+
+/*
+ * HVMOP_destroy_ioreq_server: Destroy the IOREQ Server <id> servicing domain
+ * <domid>.
+ *
+ * Any registered I/O ranges will be automatically deregistered.
+ */
+#define HVMOP_destroy_ioreq_server 21
+struct xen_hvm_destroy_ioreq_server {
+ domid_t domid; /* IN - domain to be serviced */
+ ioservid_t id; /* IN - server id */
+};
+typedef struct xen_hvm_destroy_ioreq_server xen_hvm_destroy_ioreq_server_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_destroy_ioreq_server_t);
+
+/*
+ * HVMOP_set_ioreq_server_state: Enable or disable the IOREQ Server <id> servicing
+ * domain <domid>.
+ *
+ * The IOREQ Server will not be passed any emulation requests until it is in the
+ * enabled state.
+ * Note that the contents of the ioreq_pfn and bufioreq_fn (see
+ * HVMOP_get_ioreq_server_info) are not meaningful until the IOREQ Server is in
+ * the enabled state.
+ */
+#define HVMOP_set_ioreq_server_state 22
+struct xen_hvm_set_ioreq_server_state {
+ domid_t domid; /* IN - domain to be serviced */
+ ioservid_t id; /* IN - server id */
+ uint8_t enabled; /* IN - enabled? */
+};
+typedef struct xen_hvm_set_ioreq_server_state xen_hvm_set_ioreq_server_state_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_ioreq_server_state_t);
+
+#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+
+#if defined(__i386__) || defined(__x86_64__)
+
+/*
+ * HVMOP_set_evtchn_upcall_vector: Set a <vector> that should be used for event
+ * channel upcalls on the specified <vcpu>. If set,
+ * this vector will be used in preference to the
+ * domain global callback via (see
+ * HVM_PARAM_CALLBACK_IRQ).
+ */
+#define HVMOP_set_evtchn_upcall_vector 23
+struct xen_hvm_evtchn_upcall_vector {
+ uint32_t vcpu;
+ uint8_t vector;
+};
+typedef struct xen_hvm_evtchn_upcall_vector xen_hvm_evtchn_upcall_vector_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_evtchn_upcall_vector_t);
+
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
+#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * hvm/hvm_xs_strings.h
+ *
+ * HVM xenstore strings used in HVMLOADER.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PUBLIC_HVM_HVM_XS_STRINGS_H__
+#define __XEN_PUBLIC_HVM_HVM_XS_STRINGS_H__
+
+#define HVM_XS_HVMLOADER "hvmloader"
+#define HVM_XS_BIOS "hvmloader/bios"
+#define HVM_XS_GENERATION_ID_ADDRESS "hvmloader/generation-id-address"
+#define HVM_XS_ALLOW_MEMORY_RELOCATE "hvmloader/allow-memory-relocate"
+
+/* The following values allow additional ACPI tables to be added to the
+ * virtual ACPI BIOS that hvmloader constructs. The values specify the guest
+ * physical address and length of a block of ACPI tables to add. The format of
+ * the block is simply concatenated raw tables (which specify their own length
+ * in the ACPI header).
+ */
+#define HVM_XS_ACPI_PT_ADDRESS "hvmloader/acpi/address"
+#define HVM_XS_ACPI_PT_LENGTH "hvmloader/acpi/length"
+
+/* Any number of SMBIOS types can be passed through to an HVM guest using
+ * the following xenstore values. The values specify the guest physical
+ * address and length of a block of SMBIOS structures for hvmloader to use.
+ * The block is formatted in the following way:
+ *
+ * <length><struct><length><struct>...
+ *
+ * Each length separator is a 32b integer indicating the length of the next
+ * SMBIOS structure. For DMTF defined types (0 - 121), the passed in struct
+ * will replace the default structure in hvmloader. In addition, any
+ * OEM/vendortypes (128 - 255) will all be added.
+ */
+#define HVM_XS_SMBIOS_PT_ADDRESS "hvmloader/smbios/address"
+#define HVM_XS_SMBIOS_PT_LENGTH "hvmloader/smbios/length"
+
+/* Set to 1 to enable SMBIOS default portable battery (type 22) values. */
+#define HVM_XS_SMBIOS_DEFAULT_BATTERY "hvmloader/smbios/default_battery"
+
+/* The following xenstore values are used to override some of the default
+ * string values in the SMBIOS table constructed in hvmloader.
+ */
+#define HVM_XS_BIOS_STRINGS "bios-strings"
+#define HVM_XS_BIOS_VENDOR "bios-strings/bios-vendor"
+#define HVM_XS_BIOS_VERSION "bios-strings/bios-version"
+#define HVM_XS_SYSTEM_MANUFACTURER "bios-strings/system-manufacturer"
+#define HVM_XS_SYSTEM_PRODUCT_NAME "bios-strings/system-product-name"
+#define HVM_XS_SYSTEM_VERSION "bios-strings/system-version"
+#define HVM_XS_SYSTEM_SERIAL_NUMBER "bios-strings/system-serial-number"
+#define HVM_XS_ENCLOSURE_MANUFACTURER "bios-strings/enclosure-manufacturer"
+#define HVM_XS_ENCLOSURE_SERIAL_NUMBER "bios-strings/enclosure-serial-number"
+#define HVM_XS_BATTERY_MANUFACTURER "bios-strings/battery-manufacturer"
+#define HVM_XS_BATTERY_DEVICE_NAME "bios-strings/battery-device-name"
+
+/* 1 to 99 OEM strings can be set in xenstore using values of the form
+ * below. These strings will be loaded into the SMBIOS type 11 structure.
+ */
+#define HVM_XS_OEM_STRINGS "bios-strings/oem-%d"
+
+#endif /* __XEN_PUBLIC_HVM_HVM_XS_STRINGS_H__ */
--- /dev/null
+/*
+ * ioreq.h: I/O request definitions for device models
+ * Copyright (c) 2004, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _IOREQ_H_
+#define _IOREQ_H_
+
+#define IOREQ_READ 1
+#define IOREQ_WRITE 0
+
+#define STATE_IOREQ_NONE 0
+#define STATE_IOREQ_READY 1
+#define STATE_IOREQ_INPROCESS 2
+#define STATE_IORESP_READY 3
+
+#define IOREQ_TYPE_PIO 0 /* pio */
+#define IOREQ_TYPE_COPY 1 /* mmio ops */
+#define IOREQ_TYPE_PCI_CONFIG 2
+#define IOREQ_TYPE_TIMEOFFSET 7
+#define IOREQ_TYPE_INVALIDATE 8 /* mapcache */
+
+/*
+ * VMExit dispatcher should cooperate with instruction decoder to
+ * prepare this structure and notify service OS and DM by sending
+ * virq.
+ *
+ * For I/O type IOREQ_TYPE_PCI_CONFIG, the physical address is formatted
+ * as follows:
+ *
+ * 63....48|47..40|39..35|34..32|31........0
+ * SEGMENT |BUS |DEV |FN |OFFSET
+ */
+struct ioreq {
+ uint64_t addr; /* physical address */
+ uint64_t data; /* data (or paddr of data) */
+ uint32_t count; /* for rep prefixes */
+ uint32_t size; /* size in bytes */
+ uint32_t vp_eport; /* evtchn for notifications to/from device model */
+ uint16_t _pad0;
+ uint8_t state:4;
+ uint8_t data_is_ptr:1; /* if 1, data above is the guest paddr
+ * of the real data to use. */
+ uint8_t dir:1; /* 1=read, 0=write */
+ uint8_t df:1;
+ uint8_t _pad1:1;
+ uint8_t type; /* I/O type */
+};
+typedef struct ioreq ioreq_t;
+
+struct shared_iopage {
+ struct ioreq vcpu_ioreq[1];
+};
+typedef struct shared_iopage shared_iopage_t;
+
+struct buf_ioreq {
+ uint8_t type; /* I/O type */
+ uint8_t pad:1;
+ uint8_t dir:1; /* 1=read, 0=write */
+ uint8_t size:2; /* 0=>1, 1=>2, 2=>4, 3=>8. If 8, use two buf_ioreqs */
+ uint32_t addr:20;/* physical address */
+ uint32_t data; /* data */
+};
+typedef struct buf_ioreq buf_ioreq_t;
+
+#define IOREQ_BUFFER_SLOT_NUM 511 /* 8 bytes each, plus 2 4-byte indexes */
+struct buffered_iopage {
+ unsigned int read_pointer;
+ unsigned int write_pointer;
+ buf_ioreq_t buf_ioreq[IOREQ_BUFFER_SLOT_NUM];
+}; /* NB. Size of this structure must be no greater than one page. */
+typedef struct buffered_iopage buffered_iopage_t;
+
+/*
+ * ACPI Control/Event register locations. Location is controlled by a
+ * version number in HVM_PARAM_ACPI_IOPORTS_LOCATION.
+ */
+
+/* Version 0 (default): Traditional Xen locations. */
+#define ACPI_PM1A_EVT_BLK_ADDRESS_V0 0x1f40
+#define ACPI_PM1A_CNT_BLK_ADDRESS_V0 (ACPI_PM1A_EVT_BLK_ADDRESS_V0 + 0x04)
+#define ACPI_PM_TMR_BLK_ADDRESS_V0 (ACPI_PM1A_EVT_BLK_ADDRESS_V0 + 0x08)
+#define ACPI_GPE0_BLK_ADDRESS_V0 (ACPI_PM_TMR_BLK_ADDRESS_V0 + 0x20)
+#define ACPI_GPE0_BLK_LEN_V0 0x08
+
+/* Version 1: Locations preferred by modern Qemu. */
+#define ACPI_PM1A_EVT_BLK_ADDRESS_V1 0xb000
+#define ACPI_PM1A_CNT_BLK_ADDRESS_V1 (ACPI_PM1A_EVT_BLK_ADDRESS_V1 + 0x04)
+#define ACPI_PM_TMR_BLK_ADDRESS_V1 (ACPI_PM1A_EVT_BLK_ADDRESS_V1 + 0x08)
+#define ACPI_GPE0_BLK_ADDRESS_V1 0xafe0
+#define ACPI_GPE0_BLK_LEN_V1 0x04
+
+/* Compatibility definitions for the default location (version 0). */
+#define ACPI_PM1A_EVT_BLK_ADDRESS ACPI_PM1A_EVT_BLK_ADDRESS_V0
+#define ACPI_PM1A_CNT_BLK_ADDRESS ACPI_PM1A_CNT_BLK_ADDRESS_V0
+#define ACPI_PM_TMR_BLK_ADDRESS ACPI_PM_TMR_BLK_ADDRESS_V0
+#define ACPI_GPE0_BLK_ADDRESS ACPI_GPE0_BLK_ADDRESS_V0
+#define ACPI_GPE0_BLK_LEN ACPI_GPE0_BLK_LEN_V0
+
+
+#endif /* _IOREQ_H_ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PUBLIC_HVM_PARAMS_H__
+#define __XEN_PUBLIC_HVM_PARAMS_H__
+
+#include "hvm_op.h"
+
+/*
+ * Parameter space for HVMOP_{set,get}_param.
+ */
+
+/*
+ * How should CPU0 event-channel notifications be delivered?
+ * val[63:56] == 0: val[55:0] is a delivery GSI (Global System Interrupt).
+ * val[63:56] == 1: val[55:0] is a delivery PCI INTx line, as follows:
+ * Domain = val[47:32], Bus = val[31:16],
+ * DevFn = val[15: 8], IntX = val[ 1: 0]
+ * val[63:56] == 2: val[7:0] is a vector number, check for
+ * XENFEAT_hvm_callback_vector to know if this delivery
+ * method is available.
+ * If val == 0 then CPU0 event-channel notifications are not delivered.
+ */
+#define HVM_PARAM_CALLBACK_IRQ 0
+
+/*
+ * These are not used by Xen. They are here for convenience of HVM-guest
+ * xenbus implementations.
+ */
+#define HVM_PARAM_STORE_PFN 1
+#define HVM_PARAM_STORE_EVTCHN 2
+
+#define HVM_PARAM_PAE_ENABLED 4
+
+#define HVM_PARAM_IOREQ_PFN 5
+
+#define HVM_PARAM_BUFIOREQ_PFN 6
+#define HVM_PARAM_BUFIOREQ_EVTCHN 26
+
+#if defined(__i386__) || defined(__x86_64__)
+
+/*
+ * Viridian enlightenments
+ *
+ * (See http://download.microsoft.com/download/A/B/4/AB43A34E-BDD0-4FA6-BDEF-79EEF16E880B/Hypervisor%20Top%20Level%20Functional%20Specification%20v4.0.docx)
+ *
+ * To expose viridian enlightenments to the guest set this parameter
+ * to the desired feature mask. The base feature set must be present
+ * in any valid feature mask.
+ */
+#define HVM_PARAM_VIRIDIAN 9
+
+/* Base+Freq viridian feature sets:
+ *
+ * - Hypercall MSRs (HV_X64_MSR_GUEST_OS_ID and HV_X64_MSR_HYPERCALL)
+ * - APIC access MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR)
+ * - Virtual Processor index MSR (HV_X64_MSR_VP_INDEX)
+ * - Timer frequency MSRs (HV_X64_MSR_TSC_FREQUENCY and
+ * HV_X64_MSR_APIC_FREQUENCY)
+ */
+#define _HVMPV_base_freq 0
+#define HVMPV_base_freq (1 << _HVMPV_base_freq)
+
+/* Feature set modifications */
+
+/* Disable timer frequency MSRs (HV_X64_MSR_TSC_FREQUENCY and
+ * HV_X64_MSR_APIC_FREQUENCY).
+ * This modification restores the viridian feature set to the
+ * original 'base' set exposed in releases prior to Xen 4.4.
+ */
+#define _HVMPV_no_freq 1
+#define HVMPV_no_freq (1 << _HVMPV_no_freq)
+
+/* Enable Partition Time Reference Counter (HV_X64_MSR_TIME_REF_COUNT) */
+#define _HVMPV_time_ref_count 2
+#define HVMPV_time_ref_count (1 << _HVMPV_time_ref_count)
+
+/* Enable Reference TSC Page (HV_X64_MSR_REFERENCE_TSC) */
+#define _HVMPV_reference_tsc 3
+#define HVMPV_reference_tsc (1 << _HVMPV_reference_tsc)
+
+#define HVMPV_feature_mask \
+ (HVMPV_base_freq | \
+ HVMPV_no_freq | \
+ HVMPV_time_ref_count | \
+ HVMPV_reference_tsc)
+
+#endif
+
+/*
+ * Set mode for virtual timers (currently x86 only):
+ * delay_for_missed_ticks (default):
+ * Do not advance a vcpu's time beyond the correct delivery time for
+ * interrupts that have been missed due to preemption. Deliver missed
+ * interrupts when the vcpu is rescheduled and advance the vcpu's virtual
+ * time stepwise for each one.
+ * no_delay_for_missed_ticks:
+ * As above, missed interrupts are delivered, but guest time always tracks
+ * wallclock (i.e., real) time while doing so.
+ * no_missed_ticks_pending:
+ * No missed interrupts are held pending. Instead, to ensure ticks are
+ * delivered at some non-zero rate, if we detect missed ticks then the
+ * internal tick alarm is not disabled if the VCPU is preempted during the
+ * next tick period.
+ * one_missed_tick_pending:
+ * Missed interrupts are collapsed together and delivered as one 'late tick'.
+ * Guest time always tracks wallclock (i.e., real) time.
+ */
+#define HVM_PARAM_TIMER_MODE 10
+#define HVMPTM_delay_for_missed_ticks 0
+#define HVMPTM_no_delay_for_missed_ticks 1
+#define HVMPTM_no_missed_ticks_pending 2
+#define HVMPTM_one_missed_tick_pending 3
+
+/* Boolean: Enable virtual HPET (high-precision event timer)? (x86-only) */
+#define HVM_PARAM_HPET_ENABLED 11
+
+/* Identity-map page directory used by Intel EPT when CR0.PG=0. */
+#define HVM_PARAM_IDENT_PT 12
+
+/* Device Model domain, defaults to 0. */
+#define HVM_PARAM_DM_DOMAIN 13
+
+/* ACPI S state: currently support S0 and S3 on x86. */
+#define HVM_PARAM_ACPI_S_STATE 14
+
+/* TSS used on Intel when CR0.PE=0. */
+#define HVM_PARAM_VM86_TSS 15
+
+/* Boolean: Enable aligning all periodic vpts to reduce interrupts */
+#define HVM_PARAM_VPT_ALIGN 16
+
+/* Console debug shared memory ring and event channel */
+#define HVM_PARAM_CONSOLE_PFN 17
+#define HVM_PARAM_CONSOLE_EVTCHN 18
+
+/*
+ * Select location of ACPI PM1a and TMR control blocks. Currently two locations
+ * are supported, specified by version 0 or 1 in this parameter:
+ * - 0: default, use the old addresses
+ * PM1A_EVT == 0x1f40; PM1A_CNT == 0x1f44; PM_TMR == 0x1f48
+ * - 1: use the new default qemu addresses
+ * PM1A_EVT == 0xb000; PM1A_CNT == 0xb004; PM_TMR == 0xb008
+ * You can find these address definitions in <hvm/ioreq.h>
+ */
+#define HVM_PARAM_ACPI_IOPORTS_LOCATION 19
+
+/* Enable blocking memory events, async or sync (pause vcpu until response)
+ * onchangeonly indicates messages only on a change of value */
+#define HVM_PARAM_MEMORY_EVENT_CR0 20
+#define HVM_PARAM_MEMORY_EVENT_CR3 21
+#define HVM_PARAM_MEMORY_EVENT_CR4 22
+#define HVM_PARAM_MEMORY_EVENT_INT3 23
+#define HVM_PARAM_MEMORY_EVENT_SINGLE_STEP 25
+#define HVM_PARAM_MEMORY_EVENT_MSR 30
+
+#define HVMPME_MODE_MASK (3 << 0)
+#define HVMPME_mode_disabled 0
+#define HVMPME_mode_async 1
+#define HVMPME_mode_sync 2
+#define HVMPME_onchangeonly (1 << 2)
+
+/* Boolean: Enable nestedhvm (hvm only) */
+#define HVM_PARAM_NESTEDHVM 24
+
+/* Params for the mem event rings */
+#define HVM_PARAM_PAGING_RING_PFN 27
+#define HVM_PARAM_ACCESS_RING_PFN 28
+#define HVM_PARAM_SHARING_RING_PFN 29
+
+/* SHUTDOWN_* action in case of a triple fault */
+#define HVM_PARAM_TRIPLE_FAULT_REASON 31
+
+#define HVM_PARAM_IOREQ_SERVER_PFN 32
+#define HVM_PARAM_NR_IOREQ_SERVER_PAGES 33
+
+/* Location of the VM Generation ID in guest physical address space. */
+#define HVM_PARAM_VM_GENERATION_ID_ADDR 34
+
+#define HVM_NR_PARAMS 35
+
+#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
--- /dev/null
+/*
+ * pvdrivers.h: Register of PV drivers product numbers.
+ * Copyright (c) 2012, Citrix Systems Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _XEN_PUBLIC_PVDRIVERS_H_
+#define _XEN_PUBLIC_PVDRIVERS_H_
+
+/*
+ * This is the master registry of product numbers for
+ * PV drivers.
+ * If you need a new product number allocating, please
+ * post to xen-devel@lists.xensource.com. You should NOT use
+ * a product number without allocating one.
+ * If you maintain a separate versioning and distribution path
+ * for PV drivers you should have a separate product number so
+ * that your drivers can be separated from others.
+ *
+ * During development, you may use the product ID to
+ * indicate a driver which is yet to be released.
+ */
+
+#define PVDRIVERS_PRODUCT_LIST(EACH) \
+ EACH("xensource-windows", 0x0001) /* Citrix */ \
+ EACH("gplpv-windows", 0x0002) /* James Harper */ \
+ EACH("linux", 0x0003) \
+ EACH("xenserver-windows-v7.0+", 0x0004) /* Citrix */ \
+ EACH("xenserver-windows-v7.2+", 0x0005) /* Citrix */ \
+ EACH("experimental", 0xffff)
+
+#endif /* _XEN_PUBLIC_PVDRIVERS_H_ */
--- /dev/null
+/*
+ * hvm/save.h
+ *
+ * Structure definitions for HVM state that is held by Xen and must
+ * be saved along with the domain's memory and device-model state.
+ *
+ * Copyright (c) 2007 XenSource Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PUBLIC_HVM_SAVE_H__
+#define __XEN_PUBLIC_HVM_SAVE_H__
+
+/*
+ * Structures in this header *must* have the same layout in 32bit
+ * and 64bit environments: this means that all fields must be explicitly
+ * sized types and aligned to their sizes, and the structs must be
+ * a multiple of eight bytes long.
+ *
+ * Only the state necessary for saving and restoring (i.e. fields
+ * that are analogous to actual hardware state) should go in this file.
+ * Internal mechanisms should be kept in Xen-private headers.
+ */
+
+#if !defined(__GNUC__) || defined(__STRICT_ANSI__)
+#error "Anonymous structs/unions are a GNU extension."
+#endif
+
+/*
+ * Each entry is preceded by a descriptor giving its type and length
+ */
+struct hvm_save_descriptor {
+ uint16_t typecode; /* Used to demux the various types below */
+ uint16_t instance; /* Further demux within a type */
+ uint32_t length; /* In bytes, *not* including this descriptor */
+};
+
+
+/*
+ * Each entry has a datatype associated with it: for example, the CPU state
+ * is saved as a HVM_SAVE_TYPE(CPU), which has HVM_SAVE_LENGTH(CPU),
+ * and is identified by a descriptor with typecode HVM_SAVE_CODE(CPU).
+ * DECLARE_HVM_SAVE_TYPE binds these things together with some type-system
+ * ugliness.
+ */
+
+#ifdef __XEN__
+# define DECLARE_HVM_SAVE_TYPE_COMPAT(_x, _code, _type, _ctype, _fix) \
+ static inline int __HVM_SAVE_FIX_COMPAT_##_x(void *h) { return _fix(h); } \
+ struct __HVM_SAVE_TYPE_##_x { _type t; char c[_code]; char cpt[2];}; \
+ struct __HVM_SAVE_TYPE_COMPAT_##_x { _ctype t; }
+
+# include <xen/lib.h> /* BUG() */
+# define DECLARE_HVM_SAVE_TYPE(_x, _code, _type) \
+ static inline int __HVM_SAVE_FIX_COMPAT_##_x(void *h) { BUG(); return -1; } \
+ struct __HVM_SAVE_TYPE_##_x { _type t; char c[_code]; char cpt[1];}; \
+ struct __HVM_SAVE_TYPE_COMPAT_##_x { _type t; }
+#else
+# define DECLARE_HVM_SAVE_TYPE_COMPAT(_x, _code, _type, _ctype, _fix) \
+ struct __HVM_SAVE_TYPE_##_x { _type t; char c[_code]; char cpt[2];}
+
+# define DECLARE_HVM_SAVE_TYPE(_x, _code, _type) \
+ struct __HVM_SAVE_TYPE_##_x { _type t; char c[_code]; char cpt[1];}
+#endif
+
+#define HVM_SAVE_TYPE(_x) typeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->t)
+#define HVM_SAVE_LENGTH(_x) (sizeof (HVM_SAVE_TYPE(_x)))
+#define HVM_SAVE_CODE(_x) (sizeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->c))
+
+#ifdef __XEN__
+# define HVM_SAVE_TYPE_COMPAT(_x) typeof (((struct __HVM_SAVE_TYPE_COMPAT_##_x *)(0))->t)
+# define HVM_SAVE_LENGTH_COMPAT(_x) (sizeof (HVM_SAVE_TYPE_COMPAT(_x)))
+
+# define HVM_SAVE_HAS_COMPAT(_x) (sizeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->cpt)-1)
+# define HVM_SAVE_FIX_COMPAT(_x, _dst) __HVM_SAVE_FIX_COMPAT_##_x(_dst)
+#endif
+
+/*
+ * The series of save records is teminated by a zero-type, zero-length
+ * descriptor.
+ */
+
+struct hvm_save_end {};
+DECLARE_HVM_SAVE_TYPE(END, 0, struct hvm_save_end);
+
+#if defined(__i386__) || defined(__x86_64__)
+#include "../arch-x86/hvm/save.h"
+#elif defined(__arm__) || defined(__aarch64__)
+#include "../arch-arm/hvm/save.h"
+#else
+#error "unsupported architecture"
+#endif
+
+#endif /* __XEN_PUBLIC_HVM_SAVE_H__ */
--- /dev/null
+/******************************************************************************
+ * blkif.h
+ *
+ * Unified block-device I/O interface for Xen guest OSes.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2003-2004, Keir Fraser
+ * Copyright (c) 2012, Spectra Logic Corporation
+ */
+
+#ifndef __XEN_PUBLIC_IO_BLKIF_H__
+#define __XEN_PUBLIC_IO_BLKIF_H__
+
+#include "ring.h"
+#include "../grant_table.h"
+
+/*
+ * Front->back notifications: When enqueuing a new request, sending a
+ * notification can be made conditional on req_event (i.e., the generic
+ * hold-off mechanism provided by the ring macros). Backends must set
+ * req_event appropriately (e.g., using RING_FINAL_CHECK_FOR_REQUESTS()).
+ *
+ * Back->front notifications: When enqueuing a new response, sending a
+ * notification can be made conditional on rsp_event (i.e., the generic
+ * hold-off mechanism provided by the ring macros). Frontends must set
+ * rsp_event appropriately (e.g., using RING_FINAL_CHECK_FOR_RESPONSES()).
+ */
+
+#ifndef blkif_vdev_t
+#define blkif_vdev_t uint16_t
+#endif
+#define blkif_sector_t uint64_t
+
+/*
+ * Feature and Parameter Negotiation
+ * =================================
+ * The two halves of a Xen block driver utilize nodes within the XenStore to
+ * communicate capabilities and to negotiate operating parameters. This
+ * section enumerates these nodes which reside in the respective front and
+ * backend portions of the XenStore, following the XenBus convention.
+ *
+ * All data in the XenStore is stored as strings. Nodes specifying numeric
+ * values are encoded in decimal. Integer value ranges listed below are
+ * expressed as fixed sized integer types capable of storing the conversion
+ * of a properly formated node string, without loss of information.
+ *
+ * Any specified default value is in effect if the corresponding XenBus node
+ * is not present in the XenStore.
+ *
+ * XenStore nodes in sections marked "PRIVATE" are solely for use by the
+ * driver side whose XenBus tree contains them.
+ *
+ * XenStore nodes marked "DEPRECATED" in their notes section should only be
+ * used to provide interoperability with legacy implementations.
+ *
+ * See the XenBus state transition diagram below for details on when XenBus
+ * nodes must be published and when they can be queried.
+ *
+ *****************************************************************************
+ * Backend XenBus Nodes
+ *****************************************************************************
+ *
+ *------------------ Backend Device Identification (PRIVATE) ------------------
+ *
+ * mode
+ * Values: "r" (read only), "w" (writable)
+ *
+ * The read or write access permissions to the backing store to be
+ * granted to the frontend.
+ *
+ * params
+ * Values: string
+ *
+ * A free formatted string providing sufficient information for the
+ * backend driver to open the backing device. (e.g. the path to the
+ * file or block device representing the backing store.)
+ *
+ * type
+ * Values: "file", "phy", "tap"
+ *
+ * The type of the backing device/object.
+ *
+ *
+ * direct-io-safe
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ *
+ * The underlying storage is not affected by the direct IO memory
+ * lifetime bug. See:
+ * http://lists.xen.org/archives/html/xen-devel/2012-12/msg01154.html
+ *
+ * Therefore this option gives the backend permission to use
+ * O_DIRECT, notwithstanding that bug.
+ *
+ * That is, if this option is enabled, use of O_DIRECT is safe,
+ * in circumstances where we would normally have avoided it as a
+ * workaround for that bug. This option is not relevant for all
+ * backends, and even not necessarily supported for those for
+ * which it is relevant. A backend which knows that it is not
+ * affected by the bug can ignore this option.
+ *
+ * This option doesn't require a backend to use O_DIRECT, so it
+ * should not be used to try to control the caching behaviour.
+ *
+ *--------------------------------- Features ---------------------------------
+ *
+ * feature-barrier
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ *
+ * A value of "1" indicates that the backend can process requests
+ * containing the BLKIF_OP_WRITE_BARRIER request opcode. Requests
+ * of this type may still be returned at any time with the
+ * BLKIF_RSP_EOPNOTSUPP result code.
+ *
+ * feature-flush-cache
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ *
+ * A value of "1" indicates that the backend can process requests
+ * containing the BLKIF_OP_FLUSH_DISKCACHE request opcode. Requests
+ * of this type may still be returned at any time with the
+ * BLKIF_RSP_EOPNOTSUPP result code.
+ *
+ * feature-discard
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ *
+ * A value of "1" indicates that the backend can process requests
+ * containing the BLKIF_OP_DISCARD request opcode. Requests
+ * of this type may still be returned at any time with the
+ * BLKIF_RSP_EOPNOTSUPP result code.
+ *
+ * feature-persistent
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ * Notes: 7
+ *
+ * A value of "1" indicates that the backend can keep the grants used
+ * by the frontend driver mapped, so the same set of grants should be
+ * used in all transactions. The maximum number of grants the backend
+ * can map persistently depends on the implementation, but ideally it
+ * should be RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST. Using this
+ * feature the backend doesn't need to unmap each grant, preventing
+ * costly TLB flushes. The backend driver should only map grants
+ * persistently if the frontend supports it. If a backend driver chooses
+ * to use the persistent protocol when the frontend doesn't support it,
+ * it will probably hit the maximum number of persistently mapped grants
+ * (due to the fact that the frontend won't be reusing the same grants),
+ * and fall back to non-persistent mode. Backend implementations may
+ * shrink or expand the number of persistently mapped grants without
+ * notifying the frontend depending on memory constraints (this might
+ * cause a performance degradation).
+ *
+ * If a backend driver wants to limit the maximum number of persistently
+ * mapped grants to a value less than RING_SIZE *
+ * BLKIF_MAX_SEGMENTS_PER_REQUEST a LRU strategy should be used to
+ * discard the grants that are less commonly used. Using a LRU in the
+ * backend driver paired with a LIFO queue in the frontend will
+ * allow us to have better performance in this scenario.
+ *
+ *----------------------- Request Transport Parameters ------------------------
+ *
+ * max-ring-page-order
+ * Values: <uint32_t>
+ * Default Value: 0
+ * Notes: 1, 3
+ *
+ * The maximum supported size of the request ring buffer in units of
+ * lb(machine pages). (e.g. 0 == 1 page, 1 = 2 pages, 2 == 4 pages,
+ * etc.).
+ *
+ * max-ring-pages
+ * Values: <uint32_t>
+ * Default Value: 1
+ * Notes: DEPRECATED, 2, 3
+ *
+ * The maximum supported size of the request ring buffer in units of
+ * machine pages. The value must be a power of 2.
+ *
+ *------------------------- Backend Device Properties -------------------------
+ *
+ * discard-enable
+ * Values: 0/1 (boolean)
+ * Default Value: 1
+ *
+ * This optional property, set by the toolstack, instructs the backend
+ * to offer discard to the frontend. If the property is missing the
+ * backend should offer discard if the backing storage actually supports
+ * it. This optional property, set by the toolstack, requests that the
+ * backend offer, or not offer, discard to the frontend.
+ *
+ * discard-alignment
+ * Values: <uint32_t>
+ * Default Value: 0
+ * Notes: 4, 5
+ *
+ * The offset, in bytes from the beginning of the virtual block device,
+ * to the first, addressable, discard extent on the underlying device.
+ *
+ * discard-granularity
+ * Values: <uint32_t>
+ * Default Value: <"sector-size">
+ * Notes: 4
+ *
+ * The size, in bytes, of the individually addressable discard extents
+ * of the underlying device.
+ *
+ * discard-secure
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ * Notes: 10
+ *
+ * A value of "1" indicates that the backend can process BLKIF_OP_DISCARD
+ * requests with the BLKIF_DISCARD_SECURE flag set.
+ *
+ * info
+ * Values: <uint32_t> (bitmap)
+ *
+ * A collection of bit flags describing attributes of the backing
+ * device. The VDISK_* macros define the meaning of each bit
+ * location.
+ *
+ * sector-size
+ * Values: <uint32_t>
+ *
+ * The logical sector size, in bytes, of the backend device.
+ *
+ * physical-sector-size
+ * Values: <uint32_t>
+ *
+ * The physical sector size, in bytes, of the backend device.
+ *
+ * sectors
+ * Values: <uint64_t>
+ *
+ * The size of the backend device, expressed in units of its logical
+ * sector size ("sector-size").
+ *
+ *****************************************************************************
+ * Frontend XenBus Nodes
+ *****************************************************************************
+ *
+ *----------------------- Request Transport Parameters -----------------------
+ *
+ * event-channel
+ * Values: <uint32_t>
+ *
+ * The identifier of the Xen event channel used to signal activity
+ * in the ring buffer.
+ *
+ * ring-ref
+ * Values: <uint32_t>
+ * Notes: 6
+ *
+ * The Xen grant reference granting permission for the backend to map
+ * the sole page in a single page sized ring buffer.
+ *
+ * ring-ref%u
+ * Values: <uint32_t>
+ * Notes: 6
+ *
+ * For a frontend providing a multi-page ring, a "number of ring pages"
+ * sized list of nodes, each containing a Xen grant reference granting
+ * permission for the backend to map the page of the ring located
+ * at page index "%u". Page indexes are zero based.
+ *
+ * protocol
+ * Values: string (XEN_IO_PROTO_ABI_*)
+ * Default Value: XEN_IO_PROTO_ABI_NATIVE
+ *
+ * The machine ABI rules governing the format of all ring request and
+ * response structures.
+ *
+ * ring-page-order
+ * Values: <uint32_t>
+ * Default Value: 0
+ * Maximum Value: MAX(ffs(max-ring-pages) - 1, max-ring-page-order)
+ * Notes: 1, 3
+ *
+ * The size of the frontend allocated request ring buffer in units
+ * of lb(machine pages). (e.g. 0 == 1 page, 1 = 2 pages, 2 == 4 pages,
+ * etc.).
+ *
+ * num-ring-pages
+ * Values: <uint32_t>
+ * Default Value: 1
+ * Maximum Value: MAX(max-ring-pages,(0x1 << max-ring-page-order))
+ * Notes: DEPRECATED, 2, 3
+ *
+ * The size of the frontend allocated request ring buffer in units of
+ * machine pages. The value must be a power of 2.
+ *
+ * feature-persistent
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ * Notes: 7, 8, 9
+ *
+ * A value of "1" indicates that the frontend will reuse the same grants
+ * for all transactions, allowing the backend to map them with write
+ * access (even when it should be read-only). If the frontend hits the
+ * maximum number of allowed persistently mapped grants, it can fallback
+ * to non persistent mode. This will cause a performance degradation,
+ * since the the backend driver will still try to map those grants
+ * persistently. Since the persistent grants protocol is compatible with
+ * the previous protocol, a frontend driver can choose to work in
+ * persistent mode even when the backend doesn't support it.
+ *
+ * It is recommended that the frontend driver stores the persistently
+ * mapped grants in a LIFO queue, so a subset of all persistently mapped
+ * grants gets used commonly. This is done in case the backend driver
+ * decides to limit the maximum number of persistently mapped grants
+ * to a value less than RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST.
+ *
+ *------------------------- Virtual Device Properties -------------------------
+ *
+ * device-type
+ * Values: "disk", "cdrom", "floppy", etc.
+ *
+ * virtual-device
+ * Values: <uint32_t>
+ *
+ * A value indicating the physical device to virtualize within the
+ * frontend's domain. (e.g. "The first ATA disk", "The third SCSI
+ * disk", etc.)
+ *
+ * See docs/misc/vbd-interface.txt for details on the format of this
+ * value.
+ *
+ * Notes
+ * -----
+ * (1) Multi-page ring buffer scheme first developed in the Citrix XenServer
+ * PV drivers.
+ * (2) Multi-page ring buffer scheme first used in some RedHat distributions
+ * including a distribution deployed on certain nodes of the Amazon
+ * EC2 cluster.
+ * (3) Support for multi-page ring buffers was implemented independently,
+ * in slightly different forms, by both Citrix and RedHat/Amazon.
+ * For full interoperability, block front and backends should publish
+ * identical ring parameters, adjusted for unit differences, to the
+ * XenStore nodes used in both schemes.
+ * (4) Devices that support discard functionality may internally allocate space
+ * (discardable extents) in units that are larger than the exported logical
+ * block size. If the backing device has such discardable extents the
+ * backend should provide both discard-granularity and discard-alignment.
+ * Providing just one of the two may be considered an error by the frontend.
+ * Backends supporting discard should include discard-granularity and
+ * discard-alignment even if it supports discarding individual sectors.
+ * Frontends should assume discard-alignment == 0 and discard-granularity
+ * == sector size if these keys are missing.
+ * (5) The discard-alignment parameter allows a physical device to be
+ * partitioned into virtual devices that do not necessarily begin or
+ * end on a discardable extent boundary.
+ * (6) When there is only a single page allocated to the request ring,
+ * 'ring-ref' is used to communicate the grant reference for this
+ * page to the backend. When using a multi-page ring, the 'ring-ref'
+ * node is not created. Instead 'ring-ref0' - 'ring-refN' are used.
+ * (7) When using persistent grants data has to be copied from/to the page
+ * where the grant is currently mapped. The overhead of doing this copy
+ * however doesn't suppress the speed improvement of not having to unmap
+ * the grants.
+ * (8) The frontend driver has to allow the backend driver to map all grants
+ * with write access, even when they should be mapped read-only, since
+ * further requests may reuse these grants and require write permissions.
+ * (9) Linux implementation doesn't have a limit on the maximum number of
+ * grants that can be persistently mapped in the frontend driver, but
+ * due to the frontent driver implementation it should never be bigger
+ * than RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST.
+ *(10) The discard-secure property may be present and will be set to 1 if the
+ * backing device supports secure discard.
+ */
+
+/*
+ * STATE DIAGRAMS
+ *
+ *****************************************************************************
+ * Startup *
+ *****************************************************************************
+ *
+ * Tool stack creates front and back nodes with state XenbusStateInitialising.
+ *
+ * Front Back
+ * ================================= =====================================
+ * XenbusStateInitialising XenbusStateInitialising
+ * o Query virtual device o Query backend device identification
+ * properties. data.
+ * o Setup OS device instance. o Open and validate backend device.
+ * o Publish backend features and
+ * transport parameters.
+ * |
+ * |
+ * V
+ * XenbusStateInitWait
+ *
+ * o Query backend features and
+ * transport parameters.
+ * o Allocate and initialize the
+ * request ring.
+ * o Publish transport parameters
+ * that will be in effect during
+ * this connection.
+ * |
+ * |
+ * V
+ * XenbusStateInitialised
+ *
+ * o Query frontend transport parameters.
+ * o Connect to the request ring and
+ * event channel.
+ * o Publish backend device properties.
+ * |
+ * |
+ * V
+ * XenbusStateConnected
+ *
+ * o Query backend device properties.
+ * o Finalize OS virtual device
+ * instance.
+ * |
+ * |
+ * V
+ * XenbusStateConnected
+ *
+ * Note: Drivers that do not support any optional features, or the negotiation
+ * of transport parameters, can skip certain states in the state machine:
+ *
+ * o A frontend may transition to XenbusStateInitialised without
+ * waiting for the backend to enter XenbusStateInitWait. In this
+ * case, default transport parameters are in effect and any
+ * transport parameters published by the frontend must contain
+ * their default values.
+ *
+ * o A backend may transition to XenbusStateInitialised, bypassing
+ * XenbusStateInitWait, without waiting for the frontend to first
+ * enter the XenbusStateInitialised state. In this case, default
+ * transport parameters are in effect and any transport parameters
+ * published by the backend must contain their default values.
+ *
+ * Drivers that support optional features and/or transport parameter
+ * negotiation must tolerate these additional state transition paths.
+ * In general this means performing the work of any skipped state
+ * transition, if it has not already been performed, in addition to the
+ * work associated with entry into the current state.
+ */
+
+/*
+ * REQUEST CODES.
+ */
+#define BLKIF_OP_READ 0
+#define BLKIF_OP_WRITE 1
+/*
+ * All writes issued prior to a request with the BLKIF_OP_WRITE_BARRIER
+ * operation code ("barrier request") must be completed prior to the
+ * execution of the barrier request. All writes issued after the barrier
+ * request must not execute until after the completion of the barrier request.
+ *
+ * Optional. See "feature-barrier" XenBus node documentation above.
+ */
+#define BLKIF_OP_WRITE_BARRIER 2
+/*
+ * Commit any uncommitted contents of the backing device's volatile cache
+ * to stable storage.
+ *
+ * Optional. See "feature-flush-cache" XenBus node documentation above.
+ */
+#define BLKIF_OP_FLUSH_DISKCACHE 3
+/*
+ * Used in SLES sources for device specific command packet
+ * contained within the request. Reserved for that purpose.
+ */
+#define BLKIF_OP_RESERVED_1 4
+/*
+ * Indicate to the backend device that a region of storage is no longer in
+ * use, and may be discarded at any time without impact to the client. If
+ * the BLKIF_DISCARD_SECURE flag is set on the request, all copies of the
+ * discarded region on the device must be rendered unrecoverable before the
+ * command returns.
+ *
+ * This operation is analogous to performing a trim (ATA) or unamp (SCSI),
+ * command on a native device.
+ *
+ * More information about trim/unmap operations can be found at:
+ * http://t13.org/Documents/UploadedDocuments/docs2008/
+ * e07154r6-Data_Set_Management_Proposal_for_ATA-ACS2.doc
+ * http://www.seagate.com/staticfiles/support/disc/manuals/
+ * Interface%20manuals/100293068c.pdf
+ *
+ * Optional. See "feature-discard", "discard-alignment",
+ * "discard-granularity", and "discard-secure" in the XenBus node
+ * documentation above.
+ */
+#define BLKIF_OP_DISCARD 5
+
+/*
+ * Recognized if "feature-max-indirect-segments" in present in the backend
+ * xenbus info. The "feature-max-indirect-segments" node contains the maximum
+ * number of segments allowed by the backend per request. If the node is
+ * present, the frontend might use blkif_request_indirect structs in order to
+ * issue requests with more than BLKIF_MAX_SEGMENTS_PER_REQUEST (11). The
+ * maximum number of indirect segments is fixed by the backend, but the
+ * frontend can issue requests with any number of indirect segments as long as
+ * it's less than the number provided by the backend. The indirect_grefs field
+ * in blkif_request_indirect should be filled by the frontend with the
+ * grant references of the pages that are holding the indirect segments.
+ * These pages are filled with an array of blkif_request_segment that hold the
+ * information about the segments. The number of indirect pages to use is
+ * determined by the number of segments an indirect request contains. Every
+ * indirect page can contain a maximum of
+ * (PAGE_SIZE / sizeof(struct blkif_request_segment)) segments, so to
+ * calculate the number of indirect pages to use we have to do
+ * ceil(indirect_segments / (PAGE_SIZE / sizeof(struct blkif_request_segment))).
+ *
+ * If a backend does not recognize BLKIF_OP_INDIRECT, it should *not*
+ * create the "feature-max-indirect-segments" node!
+ */
+#define BLKIF_OP_INDIRECT 6
+
+/*
+ * Maximum scatter/gather segments per request.
+ * This is carefully chosen so that sizeof(blkif_ring_t) <= PAGE_SIZE.
+ * NB. This could be 12 if the ring indexes weren't stored in the same page.
+ */
+#define BLKIF_MAX_SEGMENTS_PER_REQUEST 11
+
+/*
+ * Maximum number of indirect pages to use per request.
+ */
+#define BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST 8
+
+/*
+ * NB. first_sect and last_sect in blkif_request_segment, as well as
+ * sector_number in blkif_request, are always expressed in 512-byte units.
+ * However they must be properly aligned to the real sector size of the
+ * physical disk, which is reported in the "physical-sector-size" node in
+ * the backend xenbus info. Also the xenbus "sectors" node is expressed in
+ * 512-byte units.
+ */
+struct blkif_request_segment {
+ grant_ref_t gref; /* reference to I/O buffer frame */
+ /* @first_sect: first sector in frame to transfer (inclusive). */
+ /* @last_sect: last sector in frame to transfer (inclusive). */
+ uint8_t first_sect, last_sect;
+};
+
+/*
+ * Starting ring element for any I/O request.
+ */
+struct blkif_request {
+ uint8_t operation; /* BLKIF_OP_??? */
+ uint8_t nr_segments; /* number of segments */
+ blkif_vdev_t handle; /* only for read/write requests */
+ uint64_t id; /* private guest value, echoed in resp */
+ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
+ struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+typedef struct blkif_request blkif_request_t;
+
+/*
+ * Cast to this structure when blkif_request.operation == BLKIF_OP_DISCARD
+ * sizeof(struct blkif_request_discard) <= sizeof(struct blkif_request)
+ */
+struct blkif_request_discard {
+ uint8_t operation; /* BLKIF_OP_DISCARD */
+ uint8_t flag; /* BLKIF_DISCARD_SECURE or zero */
+#define BLKIF_DISCARD_SECURE (1<<0) /* ignored if discard-secure=0 */
+ blkif_vdev_t handle; /* same as for read/write requests */
+ uint64_t id; /* private guest value, echoed in resp */
+ blkif_sector_t sector_number;/* start sector idx on disk */
+ uint64_t nr_sectors; /* number of contiguous sectors to discard*/
+};
+typedef struct blkif_request_discard blkif_request_discard_t;
+
+struct blkif_request_indirect {
+ uint8_t operation; /* BLKIF_OP_INDIRECT */
+ uint8_t indirect_op; /* BLKIF_OP_{READ/WRITE} */
+ uint16_t nr_segments; /* number of segments */
+ uint64_t id; /* private guest value, echoed in resp */
+ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
+ blkif_vdev_t handle; /* same as for read/write requests */
+ grant_ref_t indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
+#ifdef __i386__
+ uint64_t pad; /* Make it 64 byte aligned on i386 */
+#endif
+};
+typedef struct blkif_request_indirect blkif_request_indirect_t;
+
+struct blkif_response {
+ uint64_t id; /* copied from request */
+ uint8_t operation; /* copied from request */
+ int16_t status; /* BLKIF_RSP_??? */
+};
+typedef struct blkif_response blkif_response_t;
+
+/*
+ * STATUS RETURN CODES.
+ */
+ /* Operation not supported (only happens on barrier writes). */
+#define BLKIF_RSP_EOPNOTSUPP -2
+ /* Operation failed for some unspecified reason (-EIO). */
+#define BLKIF_RSP_ERROR -1
+ /* Operation completed successfully. */
+#define BLKIF_RSP_OKAY 0
+
+/*
+ * Generate blkif ring structures and types.
+ */
+DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response);
+
+#define VDISK_CDROM 0x1
+#define VDISK_REMOVABLE 0x2
+#define VDISK_READONLY 0x4
+
+#endif /* __XEN_PUBLIC_IO_BLKIF_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * console.h
+ *
+ * Console I/O interface for Xen guest OSes.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2005, Keir Fraser
+ */
+
+#ifndef __XEN_PUBLIC_IO_CONSOLE_H__
+#define __XEN_PUBLIC_IO_CONSOLE_H__
+
+typedef uint32_t XENCONS_RING_IDX;
+
+#define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1))
+
+struct xencons_interface {
+ char in[1024];
+ char out[2048];
+ XENCONS_RING_IDX in_cons, in_prod;
+ XENCONS_RING_IDX out_cons, out_prod;
+};
+
+#endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/*
+ * fbif.h -- Xen virtual frame buffer device
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
+ * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
+ */
+
+#ifndef __XEN_PUBLIC_IO_FBIF_H__
+#define __XEN_PUBLIC_IO_FBIF_H__
+
+/* Out events (frontend -> backend) */
+
+/*
+ * Out events may be sent only when requested by backend, and receipt
+ * of an unknown out event is an error.
+ */
+
+/* Event type 1 currently not used */
+/*
+ * Framebuffer update notification event
+ * Capable frontend sets feature-update in xenstore.
+ * Backend requests it by setting request-update in xenstore.
+ */
+#define XENFB_TYPE_UPDATE 2
+
+struct xenfb_update
+{
+ uint8_t type; /* XENFB_TYPE_UPDATE */
+ int32_t x; /* source x */
+ int32_t y; /* source y */
+ int32_t width; /* rect width */
+ int32_t height; /* rect height */
+};
+
+/*
+ * Framebuffer resize notification event
+ * Capable backend sets feature-resize in xenstore.
+ */
+#define XENFB_TYPE_RESIZE 3
+
+struct xenfb_resize
+{
+ uint8_t type; /* XENFB_TYPE_RESIZE */
+ int32_t width; /* width in pixels */
+ int32_t height; /* height in pixels */
+ int32_t stride; /* stride in bytes */
+ int32_t depth; /* depth in bits */
+ int32_t offset; /* offset of the framebuffer in bytes */
+};
+
+#define XENFB_OUT_EVENT_SIZE 40
+
+union xenfb_out_event
+{
+ uint8_t type;
+ struct xenfb_update update;
+ struct xenfb_resize resize;
+ char pad[XENFB_OUT_EVENT_SIZE];
+};
+
+/* In events (backend -> frontend) */
+
+/*
+ * Frontends should ignore unknown in events.
+ */
+
+/*
+ * Framebuffer refresh period advice
+ * Backend sends it to advise the frontend their preferred period of
+ * refresh. Frontends that keep the framebuffer constantly up-to-date
+ * just ignore it. Frontends that use the advice should immediately
+ * refresh the framebuffer (and send an update notification event if
+ * those have been requested), then use the update frequency to guide
+ * their periodical refreshs.
+ */
+#define XENFB_TYPE_REFRESH_PERIOD 1
+#define XENFB_NO_REFRESH 0
+
+struct xenfb_refresh_period
+{
+ uint8_t type; /* XENFB_TYPE_UPDATE_PERIOD */
+ uint32_t period; /* period of refresh, in ms,
+ * XENFB_NO_REFRESH if no refresh is needed */
+};
+
+#define XENFB_IN_EVENT_SIZE 40
+
+union xenfb_in_event
+{
+ uint8_t type;
+ struct xenfb_refresh_period refresh_period;
+ char pad[XENFB_IN_EVENT_SIZE];
+};
+
+/* shared page */
+
+#define XENFB_IN_RING_SIZE 1024
+#define XENFB_IN_RING_LEN (XENFB_IN_RING_SIZE / XENFB_IN_EVENT_SIZE)
+#define XENFB_IN_RING_OFFS 1024
+#define XENFB_IN_RING(page) \
+ ((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS))
+#define XENFB_IN_RING_REF(page, idx) \
+ (XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN])
+
+#define XENFB_OUT_RING_SIZE 2048
+#define XENFB_OUT_RING_LEN (XENFB_OUT_RING_SIZE / XENFB_OUT_EVENT_SIZE)
+#define XENFB_OUT_RING_OFFS (XENFB_IN_RING_OFFS + XENFB_IN_RING_SIZE)
+#define XENFB_OUT_RING(page) \
+ ((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS))
+#define XENFB_OUT_RING_REF(page, idx) \
+ (XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN])
+
+struct xenfb_page
+{
+ uint32_t in_cons, in_prod;
+ uint32_t out_cons, out_prod;
+
+ int32_t width; /* the width of the framebuffer (in pixels) */
+ int32_t height; /* the height of the framebuffer (in pixels) */
+ uint32_t line_length; /* the length of a row of pixels (in bytes) */
+ uint32_t mem_length; /* the length of the framebuffer (in bytes) */
+ uint8_t depth; /* the depth of a pixel (in bits) */
+
+ /*
+ * Framebuffer page directory
+ *
+ * Each directory page holds PAGE_SIZE / sizeof(*pd)
+ * framebuffer pages, and can thus map up to PAGE_SIZE *
+ * PAGE_SIZE / sizeof(*pd) bytes. With PAGE_SIZE == 4096 and
+ * sizeof(unsigned long) == 4/8, that's 4 Megs 32 bit and 2 Megs
+ * 64 bit. 256 directories give enough room for a 512 Meg
+ * framebuffer with a max resolution of 12,800x10,240. Should
+ * be enough for a while with room leftover for expansion.
+ */
+ unsigned long pd[256];
+};
+
+/*
+ * Wart: xenkbd needs to know default resolution. Put it here until a
+ * better solution is found, but don't leak it to the backend.
+ */
+#ifdef __KERNEL__
+#define XENFB_WIDTH 800
+#define XENFB_HEIGHT 600
+#define XENFB_DEPTH 32
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * fsif.h
+ *
+ * Interface to FS level split device drivers.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2007, Grzegorz Milos, <gm281@cam.ac.uk>.
+ */
+
+#ifndef __XEN_PUBLIC_IO_FSIF_H__
+#define __XEN_PUBLIC_IO_FSIF_H__
+
+#include "ring.h"
+#include "../grant_table.h"
+
+#define REQ_FILE_OPEN 1
+#define REQ_FILE_CLOSE 2
+#define REQ_FILE_READ 3
+#define REQ_FILE_WRITE 4
+#define REQ_STAT 5
+#define REQ_FILE_TRUNCATE 6
+#define REQ_REMOVE 7
+#define REQ_RENAME 8
+#define REQ_CREATE 9
+#define REQ_DIR_LIST 10
+#define REQ_CHMOD 11
+#define REQ_FS_SPACE 12
+#define REQ_FILE_SYNC 13
+
+struct fsif_open_request {
+ grant_ref_t gref;
+};
+
+struct fsif_close_request {
+ uint32_t fd;
+};
+
+struct fsif_read_request {
+ uint32_t fd;
+ int32_t pad;
+ uint64_t len;
+ uint64_t offset;
+ grant_ref_t grefs[1]; /* Variable length */
+};
+
+struct fsif_write_request {
+ uint32_t fd;
+ int32_t pad;
+ uint64_t len;
+ uint64_t offset;
+ grant_ref_t grefs[1]; /* Variable length */
+};
+
+struct fsif_stat_request {
+ uint32_t fd;
+};
+
+/* This structure is a copy of some fields from stat structure, returned
+ * via the ring. */
+struct fsif_stat_response {
+ int32_t stat_mode;
+ uint32_t stat_uid;
+ uint32_t stat_gid;
+ int32_t stat_ret;
+ int64_t stat_size;
+ int64_t stat_atime;
+ int64_t stat_mtime;
+ int64_t stat_ctime;
+};
+
+struct fsif_truncate_request {
+ uint32_t fd;
+ int32_t pad;
+ int64_t length;
+};
+
+struct fsif_remove_request {
+ grant_ref_t gref;
+};
+
+struct fsif_rename_request {
+ uint16_t old_name_offset;
+ uint16_t new_name_offset;
+ grant_ref_t gref;
+};
+
+struct fsif_create_request {
+ int8_t directory;
+ int8_t pad;
+ int16_t pad2;
+ int32_t mode;
+ grant_ref_t gref;
+};
+
+struct fsif_list_request {
+ uint32_t offset;
+ grant_ref_t gref;
+};
+
+#define NR_FILES_SHIFT 0
+#define NR_FILES_SIZE 16 /* 16 bits for the number of files mask */
+#define NR_FILES_MASK (((1ULL << NR_FILES_SIZE) - 1) << NR_FILES_SHIFT)
+#define ERROR_SIZE 32 /* 32 bits for the error mask */
+#define ERROR_SHIFT (NR_FILES_SIZE + NR_FILES_SHIFT)
+#define ERROR_MASK (((1ULL << ERROR_SIZE) - 1) << ERROR_SHIFT)
+#define HAS_MORE_SHIFT (ERROR_SHIFT + ERROR_SIZE)
+#define HAS_MORE_FLAG (1ULL << HAS_MORE_SHIFT)
+
+struct fsif_chmod_request {
+ uint32_t fd;
+ int32_t mode;
+};
+
+struct fsif_space_request {
+ grant_ref_t gref;
+};
+
+struct fsif_sync_request {
+ uint32_t fd;
+};
+
+
+/* FS operation request */
+struct fsif_request {
+ uint8_t type; /* Type of the request */
+ uint8_t pad;
+ uint16_t id; /* Request ID, copied to the response */
+ uint32_t pad2;
+ union {
+ struct fsif_open_request fopen;
+ struct fsif_close_request fclose;
+ struct fsif_read_request fread;
+ struct fsif_write_request fwrite;
+ struct fsif_stat_request fstat;
+ struct fsif_truncate_request ftruncate;
+ struct fsif_remove_request fremove;
+ struct fsif_rename_request frename;
+ struct fsif_create_request fcreate;
+ struct fsif_list_request flist;
+ struct fsif_chmod_request fchmod;
+ struct fsif_space_request fspace;
+ struct fsif_sync_request fsync;
+ } u;
+};
+typedef struct fsif_request fsif_request_t;
+
+/* FS operation response */
+struct fsif_response {
+ uint16_t id;
+ uint16_t pad1;
+ uint32_t pad2;
+ union {
+ uint64_t ret_val;
+ struct fsif_stat_response fstat;
+ } u;
+};
+
+typedef struct fsif_response fsif_response_t;
+
+#define FSIF_RING_ENTRY_SIZE 64
+
+#define FSIF_NR_READ_GNTS ((FSIF_RING_ENTRY_SIZE - sizeof(struct fsif_read_request)) / \
+ sizeof(grant_ref_t) + 1)
+#define FSIF_NR_WRITE_GNTS ((FSIF_RING_ENTRY_SIZE - sizeof(struct fsif_write_request)) / \
+ sizeof(grant_ref_t) + 1)
+
+DEFINE_RING_TYPES(fsif, struct fsif_request, struct fsif_response);
+
+#define STATE_INITIALISED "init"
+#define STATE_READY "ready"
+#define STATE_CLOSING "closing"
+#define STATE_CLOSED "closed"
+
+
+#endif
--- /dev/null
+/*
+ * kbdif.h -- Xen virtual keyboard/mouse
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
+ * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
+ */
+
+#ifndef __XEN_PUBLIC_IO_KBDIF_H__
+#define __XEN_PUBLIC_IO_KBDIF_H__
+
+/* In events (backend -> frontend) */
+
+/*
+ * Frontends should ignore unknown in events.
+ */
+
+/* Pointer movement event */
+#define XENKBD_TYPE_MOTION 1
+/* Event type 2 currently not used */
+/* Key event (includes pointer buttons) */
+#define XENKBD_TYPE_KEY 3
+/*
+ * Pointer position event
+ * Capable backend sets feature-abs-pointer in xenstore.
+ * Frontend requests ot instead of XENKBD_TYPE_MOTION by setting
+ * request-abs-update in xenstore.
+ */
+#define XENKBD_TYPE_POS 4
+
+struct xenkbd_motion
+{
+ uint8_t type; /* XENKBD_TYPE_MOTION */
+ int32_t rel_x; /* relative X motion */
+ int32_t rel_y; /* relative Y motion */
+ int32_t rel_z; /* relative Z motion (wheel) */
+};
+
+struct xenkbd_key
+{
+ uint8_t type; /* XENKBD_TYPE_KEY */
+ uint8_t pressed; /* 1 if pressed; 0 otherwise */
+ uint32_t keycode; /* KEY_* from linux/input.h */
+};
+
+struct xenkbd_position
+{
+ uint8_t type; /* XENKBD_TYPE_POS */
+ int32_t abs_x; /* absolute X position (in FB pixels) */
+ int32_t abs_y; /* absolute Y position (in FB pixels) */
+ int32_t rel_z; /* relative Z motion (wheel) */
+};
+
+#define XENKBD_IN_EVENT_SIZE 40
+
+union xenkbd_in_event
+{
+ uint8_t type;
+ struct xenkbd_motion motion;
+ struct xenkbd_key key;
+ struct xenkbd_position pos;
+ char pad[XENKBD_IN_EVENT_SIZE];
+};
+
+/* Out events (frontend -> backend) */
+
+/*
+ * Out events may be sent only when requested by backend, and receipt
+ * of an unknown out event is an error.
+ * No out events currently defined.
+ */
+
+#define XENKBD_OUT_EVENT_SIZE 40
+
+union xenkbd_out_event
+{
+ uint8_t type;
+ char pad[XENKBD_OUT_EVENT_SIZE];
+};
+
+/* shared page */
+
+#define XENKBD_IN_RING_SIZE 2048
+#define XENKBD_IN_RING_LEN (XENKBD_IN_RING_SIZE / XENKBD_IN_EVENT_SIZE)
+#define XENKBD_IN_RING_OFFS 1024
+#define XENKBD_IN_RING(page) \
+ ((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS))
+#define XENKBD_IN_RING_REF(page, idx) \
+ (XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN])
+
+#define XENKBD_OUT_RING_SIZE 1024
+#define XENKBD_OUT_RING_LEN (XENKBD_OUT_RING_SIZE / XENKBD_OUT_EVENT_SIZE)
+#define XENKBD_OUT_RING_OFFS (XENKBD_IN_RING_OFFS + XENKBD_IN_RING_SIZE)
+#define XENKBD_OUT_RING(page) \
+ ((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS))
+#define XENKBD_OUT_RING_REF(page, idx) \
+ (XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN])
+
+struct xenkbd_page
+{
+ uint32_t in_cons, in_prod;
+ uint32_t out_cons, out_prod;
+};
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/**
+ * @file
+ * @section AUTHORS
+ *
+ * Copyright (C) 2010 Rafal Wojtczuk <rafal@invisiblethingslab.com>
+ *
+ * Authors:
+ * Rafal Wojtczuk <rafal@invisiblethingslab.com>
+ * Daniel De Graaf <dgdegra@tycho.nsa.gov>
+ *
+ * @section LICENSE
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @section DESCRIPTION
+ *
+ * Originally borrowed from the Qubes OS Project, http://www.qubes-os.org,
+ * this code has been substantially rewritten to use the gntdev and gntalloc
+ * devices instead of raw MFNs and map_foreign_range.
+ *
+ * This is a library for inter-domain communication. A standard Xen ring
+ * buffer is used, with a datagram-based interface built on top. The grant
+ * reference and event channels are shared in XenStore under a user-specified
+ * path.
+ *
+ * The ring.h macros define an asymmetric interface to a shared data structure
+ * that assumes all rings reside in a single contiguous memory space. This is
+ * not suitable for vchan because the interface to the ring is symmetric except
+ * for the setup. Unlike the producer-consumer rings defined in ring.h, the
+ * size of the rings used in vchan are determined at execution time instead of
+ * compile time, so the macros in ring.h cannot be used to access the rings.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+struct ring_shared {
+ uint32_t cons, prod;
+};
+
+#define VCHAN_NOTIFY_WRITE 0x1
+#define VCHAN_NOTIFY_READ 0x2
+
+/**
+ * vchan_interface: primary shared data structure
+ */
+struct vchan_interface {
+ /**
+ * Standard consumer/producer interface, one pair per buffer
+ * left is client write, server read
+ * right is client read, server write
+ */
+ struct ring_shared left, right;
+ /**
+ * size of the rings, which determines their location
+ * 10 - at offset 1024 in ring's page
+ * 11 - at offset 2048 in ring's page
+ * 12+ - uses 2^(N-12) grants to describe the multi-page ring
+ * These should remain constant once the page is shared.
+ * Only one of the two orders can be 10 (or 11).
+ */
+ uint16_t left_order, right_order;
+ /**
+ * Shutdown detection:
+ * 0: client (or server) has exited
+ * 1: client (or server) is connected
+ * 2: client has not yet connected
+ */
+ uint8_t cli_live, srv_live;
+ /**
+ * Notification bits:
+ * VCHAN_NOTIFY_WRITE: send notify when data is written
+ * VCHAN_NOTIFY_READ: send notify when data is read (consumed)
+ * cli_notify is used for the client to inform the server of its action
+ */
+ uint8_t cli_notify, srv_notify;
+ /**
+ * Grant list: ordering is left, right. Must not extend into actual ring
+ * or grow beyond the end of the initial shared page.
+ * These should remain constant once the page is shared, to allow
+ * for possible remapping by a client that restarts.
+ */
+ uint32_t grants[0];
+};
+
--- /dev/null
+/******************************************************************************
+ * netif.h
+ *
+ * Unified network-device I/O interface for Xen guest OSes.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2003-2004, Keir Fraser
+ */
+
+#ifndef __XEN_PUBLIC_IO_NETIF_H__
+#define __XEN_PUBLIC_IO_NETIF_H__
+
+#include "ring.h"
+#include "../grant_table.h"
+
+/*
+ * Older implementation of Xen network frontend / backend has an
+ * implicit dependency on the MAX_SKB_FRAGS as the maximum number of
+ * ring slots a skb can use. Netfront / netback may not work as
+ * expected when frontend and backend have different MAX_SKB_FRAGS.
+ *
+ * A better approach is to add mechanism for netfront / netback to
+ * negotiate this value. However we cannot fix all possible
+ * frontends, so we need to define a value which states the minimum
+ * slots backend must support.
+ *
+ * The minimum value derives from older Linux kernel's MAX_SKB_FRAGS
+ * (18), which is proved to work with most frontends. Any new backend
+ * which doesn't negotiate with frontend should expect frontend to
+ * send a valid packet using slots up to this value.
+ */
+#define XEN_NETIF_NR_SLOTS_MIN 18
+
+/*
+ * Notifications after enqueuing any type of message should be conditional on
+ * the appropriate req_event or rsp_event field in the shared ring.
+ * If the client sends notification for rx requests then it should specify
+ * feature 'feature-rx-notify' via xenbus. Otherwise the backend will assume
+ * that it cannot safely queue packets (as it may not be kicked to send them).
+ */
+
+/*
+ * "feature-split-event-channels" is introduced to separate guest TX
+ * and RX notification. Backend either doesn't support this feature or
+ * advertises it via xenstore as 0 (disabled) or 1 (enabled).
+ *
+ * To make use of this feature, frontend should allocate two event
+ * channels for TX and RX, advertise them to backend as
+ * "event-channel-tx" and "event-channel-rx" respectively. If frontend
+ * doesn't want to use this feature, it just writes "event-channel"
+ * node as before.
+ */
+
+/*
+ * Multiple transmit and receive queues:
+ * If supported, the backend will write the key "multi-queue-max-queues" to
+ * the directory for that vif, and set its value to the maximum supported
+ * number of queues.
+ * Frontends that are aware of this feature and wish to use it can write the
+ * key "multi-queue-num-queues", set to the number they wish to use, which
+ * must be greater than zero, and no more than the value reported by the backend
+ * in "multi-queue-max-queues".
+ *
+ * Queues replicate the shared rings and event channels.
+ * "feature-split-event-channels" may optionally be used when using
+ * multiple queues, but is not mandatory.
+ *
+ * Each queue consists of one shared ring pair, i.e. there must be the same
+ * number of tx and rx rings.
+ *
+ * For frontends requesting just one queue, the usual event-channel and
+ * ring-ref keys are written as before, simplifying the backend processing
+ * to avoid distinguishing between a frontend that doesn't understand the
+ * multi-queue feature, and one that does, but requested only one queue.
+ *
+ * Frontends requesting two or more queues must not write the toplevel
+ * event-channel (or event-channel-{tx,rx}) and {tx,rx}-ring-ref keys,
+ * instead writing those keys under sub-keys having the name "queue-N" where
+ * N is the integer ID of the queue for which those keys belong. Queues
+ * are indexed from zero. For example, a frontend with two queues and split
+ * event channels must write the following set of queue-related keys:
+ *
+ * /local/domain/1/device/vif/0/multi-queue-num-queues = "2"
+ * /local/domain/1/device/vif/0/queue-0 = ""
+ * /local/domain/1/device/vif/0/queue-0/tx-ring-ref = "<ring-ref-tx0>"
+ * /local/domain/1/device/vif/0/queue-0/rx-ring-ref = "<ring-ref-rx0>"
+ * /local/domain/1/device/vif/0/queue-0/event-channel-tx = "<evtchn-tx0>"
+ * /local/domain/1/device/vif/0/queue-0/event-channel-rx = "<evtchn-rx0>"
+ * /local/domain/1/device/vif/0/queue-1 = ""
+ * /local/domain/1/device/vif/0/queue-1/tx-ring-ref = "<ring-ref-tx1>"
+ * /local/domain/1/device/vif/0/queue-1/rx-ring-ref = "<ring-ref-rx1"
+ * /local/domain/1/device/vif/0/queue-1/event-channel-tx = "<evtchn-tx1>"
+ * /local/domain/1/device/vif/0/queue-1/event-channel-rx = "<evtchn-rx1>"
+ *
+ * If there is any inconsistency in the XenStore data, the backend may
+ * choose not to connect any queues, instead treating the request as an
+ * error. This includes scenarios where more (or fewer) queues were
+ * requested than the frontend provided details for.
+ *
+ * Mapping of packets to queues is considered to be a function of the
+ * transmitting system (backend or frontend) and is not negotiated
+ * between the two. Guests are free to transmit packets on any queue
+ * they choose, provided it has been set up correctly. Guests must be
+ * prepared to receive packets on any queue they have requested be set up.
+ */
+
+/*
+ * "feature-no-csum-offload" should be used to turn IPv4 TCP/UDP checksum
+ * offload off or on. If it is missing then the feature is assumed to be on.
+ * "feature-ipv6-csum-offload" should be used to turn IPv6 TCP/UDP checksum
+ * offload on or off. If it is missing then the feature is assumed to be off.
+ */
+
+/*
+ * "feature-gso-tcpv4" and "feature-gso-tcpv6" advertise the capability to
+ * handle large TCP packets (in IPv4 or IPv6 form respectively). Neither
+ * frontends nor backends are assumed to be capable unless the flags are
+ * present.
+ */
+
+/*
+ * This is the 'wire' format for packets:
+ * Request 1: netif_tx_request -- NETTXF_* (any flags)
+ * [Request 2: netif_tx_extra] (only if request 1 has NETTXF_extra_info)
+ * [Request 3: netif_tx_extra] (only if request 2 has XEN_NETIF_EXTRA_MORE)
+ * Request 4: netif_tx_request -- NETTXF_more_data
+ * Request 5: netif_tx_request -- NETTXF_more_data
+ * ...
+ * Request N: netif_tx_request -- 0
+ */
+
+/* Protocol checksum field is blank in the packet (hardware offload)? */
+#define _NETTXF_csum_blank (0)
+#define NETTXF_csum_blank (1U<<_NETTXF_csum_blank)
+
+/* Packet data has been validated against protocol checksum. */
+#define _NETTXF_data_validated (1)
+#define NETTXF_data_validated (1U<<_NETTXF_data_validated)
+
+/* Packet continues in the next request descriptor. */
+#define _NETTXF_more_data (2)
+#define NETTXF_more_data (1U<<_NETTXF_more_data)
+
+/* Packet to be followed by extra descriptor(s). */
+#define _NETTXF_extra_info (3)
+#define NETTXF_extra_info (1U<<_NETTXF_extra_info)
+
+#define XEN_NETIF_MAX_TX_SIZE 0xFFFF
+struct netif_tx_request {
+ grant_ref_t gref; /* Reference to buffer page */
+ uint16_t offset; /* Offset within buffer page */
+ uint16_t flags; /* NETTXF_* */
+ uint16_t id; /* Echoed in response message. */
+ uint16_t size; /* Packet size in bytes. */
+};
+typedef struct netif_tx_request netif_tx_request_t;
+
+/* Types of netif_extra_info descriptors. */
+#define XEN_NETIF_EXTRA_TYPE_NONE (0) /* Never used - invalid */
+#define XEN_NETIF_EXTRA_TYPE_GSO (1) /* u.gso */
+#define XEN_NETIF_EXTRA_TYPE_MCAST_ADD (2) /* u.mcast */
+#define XEN_NETIF_EXTRA_TYPE_MCAST_DEL (3) /* u.mcast */
+#define XEN_NETIF_EXTRA_TYPE_MAX (4)
+
+/* netif_extra_info flags. */
+#define _XEN_NETIF_EXTRA_FLAG_MORE (0)
+#define XEN_NETIF_EXTRA_FLAG_MORE (1U<<_XEN_NETIF_EXTRA_FLAG_MORE)
+
+/* GSO types */
+#define XEN_NETIF_GSO_TYPE_NONE (0)
+#define XEN_NETIF_GSO_TYPE_TCPV4 (1)
+#define XEN_NETIF_GSO_TYPE_TCPV6 (2)
+
+/*
+ * This structure needs to fit within both netif_tx_request and
+ * netif_rx_response for compatibility.
+ */
+struct netif_extra_info {
+ uint8_t type; /* XEN_NETIF_EXTRA_TYPE_* */
+ uint8_t flags; /* XEN_NETIF_EXTRA_FLAG_* */
+
+ union {
+ /*
+ * XEN_NETIF_EXTRA_TYPE_GSO:
+ */
+ struct {
+ /*
+ * Maximum payload size of each segment. For example, for TCP this
+ * is just the path MSS.
+ */
+ uint16_t size;
+
+ /*
+ * GSO type. This determines the protocol of the packet and any
+ * extra features required to segment the packet properly.
+ */
+ uint8_t type; /* XEN_NETIF_GSO_TYPE_* */
+
+ /* Future expansion. */
+ uint8_t pad;
+
+ /*
+ * GSO features. This specifies any extra GSO features required
+ * to process this packet, such as ECN support for TCPv4.
+ */
+ uint16_t features; /* XEN_NETIF_GSO_FEAT_* */
+ } gso;
+
+ /*
+ * XEN_NETIF_EXTRA_TYPE_MCAST_{ADD,DEL}:
+ * Backend advertises availability via 'feature-multicast-control'
+ * xenbus node containing value '1'.
+ * Frontend requests this feature by advertising
+ * 'request-multicast-control' xenbus node containing value '1'.
+ * If multicast control is requested then multicast flooding is
+ * disabled and the frontend must explicitly register its interest
+ * in multicast groups using dummy transmit requests containing
+ * MCAST_{ADD,DEL} extra-info fragments.
+ */
+ struct {
+ uint8_t addr[6]; /* Address to add/remove. */
+ } mcast;
+
+ uint16_t pad[3];
+ } u;
+};
+typedef struct netif_extra_info netif_extra_info_t;
+
+struct netif_tx_response {
+ uint16_t id;
+ int16_t status; /* NETIF_RSP_* */
+};
+typedef struct netif_tx_response netif_tx_response_t;
+
+struct netif_rx_request {
+ uint16_t id; /* Echoed in response message. */
+ grant_ref_t gref; /* Reference to incoming granted frame */
+};
+typedef struct netif_rx_request netif_rx_request_t;
+
+/* Packet data has been validated against protocol checksum. */
+#define _NETRXF_data_validated (0)
+#define NETRXF_data_validated (1U<<_NETRXF_data_validated)
+
+/* Protocol checksum field is blank in the packet (hardware offload)? */
+#define _NETRXF_csum_blank (1)
+#define NETRXF_csum_blank (1U<<_NETRXF_csum_blank)
+
+/* Packet continues in the next request descriptor. */
+#define _NETRXF_more_data (2)
+#define NETRXF_more_data (1U<<_NETRXF_more_data)
+
+/* Packet to be followed by extra descriptor(s). */
+#define _NETRXF_extra_info (3)
+#define NETRXF_extra_info (1U<<_NETRXF_extra_info)
+
+struct netif_rx_response {
+ uint16_t id;
+ uint16_t offset; /* Offset in page of start of received packet */
+ uint16_t flags; /* NETRXF_* */
+ int16_t status; /* -ve: NETIF_RSP_* ; +ve: Rx'ed pkt size. */
+};
+typedef struct netif_rx_response netif_rx_response_t;
+
+/*
+ * Generate netif ring structures and types.
+ */
+
+DEFINE_RING_TYPES(netif_tx, struct netif_tx_request, struct netif_tx_response);
+DEFINE_RING_TYPES(netif_rx, struct netif_rx_request, struct netif_rx_response);
+
+#define NETIF_RSP_DROPPED -2
+#define NETIF_RSP_ERROR -1
+#define NETIF_RSP_OKAY 0
+/* No response: used for auxiliary requests (e.g., netif_tx_extra). */
+#define NETIF_RSP_NULL 1
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/*
+ * PCI Backend/Frontend Common Data Structures & Macros
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#ifndef __XEN_PCI_COMMON_H__
+#define __XEN_PCI_COMMON_H__
+
+/* Be sure to bump this number if you change this file */
+#define XEN_PCI_MAGIC "7"
+
+/* xen_pci_sharedinfo flags */
+#define _XEN_PCIF_active (0)
+#define XEN_PCIF_active (1<<_XEN_PCIF_active)
+#define _XEN_PCIB_AERHANDLER (1)
+#define XEN_PCIB_AERHANDLER (1<<_XEN_PCIB_AERHANDLER)
+#define _XEN_PCIB_active (2)
+#define XEN_PCIB_active (1<<_XEN_PCIB_active)
+
+/* xen_pci_op commands */
+#define XEN_PCI_OP_conf_read (0)
+#define XEN_PCI_OP_conf_write (1)
+#define XEN_PCI_OP_enable_msi (2)
+#define XEN_PCI_OP_disable_msi (3)
+#define XEN_PCI_OP_enable_msix (4)
+#define XEN_PCI_OP_disable_msix (5)
+#define XEN_PCI_OP_aer_detected (6)
+#define XEN_PCI_OP_aer_resume (7)
+#define XEN_PCI_OP_aer_mmio (8)
+#define XEN_PCI_OP_aer_slotreset (9)
+#define XEN_PCI_OP_enable_multi_msi (10)
+
+/* xen_pci_op error numbers */
+#define XEN_PCI_ERR_success (0)
+#define XEN_PCI_ERR_dev_not_found (-1)
+#define XEN_PCI_ERR_invalid_offset (-2)
+#define XEN_PCI_ERR_access_denied (-3)
+#define XEN_PCI_ERR_not_implemented (-4)
+/* XEN_PCI_ERR_op_failed - backend failed to complete the operation */
+#define XEN_PCI_ERR_op_failed (-5)
+
+/*
+ * it should be PAGE_SIZE-sizeof(struct xen_pci_op))/sizeof(struct msix_entry))
+ * Should not exceed 128
+ */
+#define SH_INFO_MAX_VEC 128
+
+struct xen_msix_entry {
+ uint16_t vector;
+ uint16_t entry;
+};
+struct xen_pci_op {
+ /* IN: what action to perform: XEN_PCI_OP_* */
+ uint32_t cmd;
+
+ /* OUT: will contain an error number (if any) from errno.h */
+ int32_t err;
+
+ /* IN: which device to touch */
+ uint32_t domain; /* PCI Domain/Segment */
+ uint32_t bus;
+ uint32_t devfn;
+
+ /* IN: which configuration registers to touch */
+ int32_t offset;
+ int32_t size;
+
+ /* IN/OUT: Contains the result after a READ or the value to WRITE */
+ uint32_t value;
+ /* IN: Contains extra infor for this operation */
+ uint32_t info;
+ /*IN: param for msi-x */
+ struct xen_msix_entry msix_entries[SH_INFO_MAX_VEC];
+};
+
+/*used for pcie aer handling*/
+struct xen_pcie_aer_op
+{
+
+ /* IN: what action to perform: XEN_PCI_OP_* */
+ uint32_t cmd;
+ /*IN/OUT: return aer_op result or carry error_detected state as input*/
+ int32_t err;
+
+ /* IN: which device to touch */
+ uint32_t domain; /* PCI Domain/Segment*/
+ uint32_t bus;
+ uint32_t devfn;
+};
+struct xen_pci_sharedinfo {
+ /* flags - XEN_PCIF_* */
+ uint32_t flags;
+ struct xen_pci_op op;
+ struct xen_pcie_aer_op aer_op;
+};
+
+#endif /* __XEN_PCI_COMMON_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * protocols.h
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PROTOCOLS_H__
+#define __XEN_PROTOCOLS_H__
+
+#define XEN_IO_PROTO_ABI_X86_32 "x86_32-abi"
+#define XEN_IO_PROTO_ABI_X86_64 "x86_64-abi"
+#define XEN_IO_PROTO_ABI_ARM "arm-abi"
+
+#if defined(__i386__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32
+#elif defined(__x86_64__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64
+#elif defined(__arm__) || defined(__aarch64__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_ARM
+#else
+# error arch fixup needed here
+#endif
+
+#endif
--- /dev/null
+/******************************************************************************
+ * ring.h
+ *
+ * Shared producer-consumer ring macros.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Tim Deegan and Andrew Warfield November 2004.
+ */
+
+#ifndef __XEN_PUBLIC_IO_RING_H__
+#define __XEN_PUBLIC_IO_RING_H__
+
+#include "../xen-compat.h"
+
+#if __XEN_INTERFACE_VERSION__ < 0x00030208
+#define xen_mb() mb()
+#define xen_rmb() rmb()
+#define xen_wmb() wmb()
+#endif
+
+typedef unsigned int RING_IDX;
+
+/* Round a 32-bit unsigned constant down to the nearest power of two. */
+#define __RD2(_x) (((_x) & 0x00000002) ? 0x2 : ((_x) & 0x1))
+#define __RD4(_x) (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2 : __RD2(_x))
+#define __RD8(_x) (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4 : __RD4(_x))
+#define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8 : __RD8(_x))
+#define __RD32(_x) (((_x) & 0xffff0000) ? __RD16((_x)>>16)<<16 : __RD16(_x))
+
+/*
+ * Calculate size of a shared ring, given the total available space for the
+ * ring and indexes (_sz), and the name tag of the request/response structure.
+ * A ring contains as many entries as will fit, rounded down to the nearest
+ * power of two (so we can mask with (size-1) to loop around).
+ */
+#define __CONST_RING_SIZE(_s, _sz) \
+ (__RD32(((_sz) - offsetof(struct _s##_sring, ring)) / \
+ sizeof(((struct _s##_sring *)0)->ring[0])))
+/*
+ * The same for passing in an actual pointer instead of a name tag.
+ */
+#define __RING_SIZE(_s, _sz) \
+ (__RD32(((_sz) - (long)(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
+
+/*
+ * Macros to make the correct C datatypes for a new kind of ring.
+ *
+ * To make a new ring datatype, you need to have two message structures,
+ * let's say request_t, and response_t already defined.
+ *
+ * In a header where you want the ring datatype declared, you then do:
+ *
+ * DEFINE_RING_TYPES(mytag, request_t, response_t);
+ *
+ * These expand out to give you a set of types, as you can see below.
+ * The most important of these are:
+ *
+ * mytag_sring_t - The shared ring.
+ * mytag_front_ring_t - The 'front' half of the ring.
+ * mytag_back_ring_t - The 'back' half of the ring.
+ *
+ * To initialize a ring in your code you need to know the location and size
+ * of the shared memory area (PAGE_SIZE, for instance). To initialise
+ * the front half:
+ *
+ * mytag_front_ring_t front_ring;
+ * SHARED_RING_INIT((mytag_sring_t *)shared_page);
+ * FRONT_RING_INIT(&front_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
+ *
+ * Initializing the back follows similarly (note that only the front
+ * initializes the shared ring):
+ *
+ * mytag_back_ring_t back_ring;
+ * BACK_RING_INIT(&back_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
+ */
+
+#define DEFINE_RING_TYPES(__name, __req_t, __rsp_t) \
+ \
+/* Shared ring entry */ \
+union __name##_sring_entry { \
+ __req_t req; \
+ __rsp_t rsp; \
+}; \
+ \
+/* Shared ring page */ \
+struct __name##_sring { \
+ RING_IDX req_prod, req_event; \
+ RING_IDX rsp_prod, rsp_event; \
+ union { \
+ struct { \
+ uint8_t smartpoll_active; \
+ } netif; \
+ struct { \
+ uint8_t msg; \
+ } tapif_user; \
+ uint8_t pvt_pad[4]; \
+ } private; \
+ uint8_t __pad[44]; \
+ union __name##_sring_entry ring[1]; /* variable-length */ \
+}; \
+ \
+/* "Front" end's private variables */ \
+struct __name##_front_ring { \
+ RING_IDX req_prod_pvt; \
+ RING_IDX rsp_cons; \
+ unsigned int nr_ents; \
+ struct __name##_sring *sring; \
+}; \
+ \
+/* "Back" end's private variables */ \
+struct __name##_back_ring { \
+ RING_IDX rsp_prod_pvt; \
+ RING_IDX req_cons; \
+ unsigned int nr_ents; \
+ struct __name##_sring *sring; \
+}; \
+ \
+/* Syntactic sugar */ \
+typedef struct __name##_sring __name##_sring_t; \
+typedef struct __name##_front_ring __name##_front_ring_t; \
+typedef struct __name##_back_ring __name##_back_ring_t
+
+/*
+ * Macros for manipulating rings.
+ *
+ * FRONT_RING_whatever works on the "front end" of a ring: here
+ * requests are pushed on to the ring and responses taken off it.
+ *
+ * BACK_RING_whatever works on the "back end" of a ring: here
+ * requests are taken off the ring and responses put on.
+ *
+ * N.B. these macros do NO INTERLOCKS OR FLOW CONTROL.
+ * This is OK in 1-for-1 request-response situations where the
+ * requestor (front end) never has more than RING_SIZE()-1
+ * outstanding requests.
+ */
+
+/* Initialising empty rings */
+#define SHARED_RING_INIT(_s) do { \
+ (_s)->req_prod = (_s)->rsp_prod = 0; \
+ (_s)->req_event = (_s)->rsp_event = 1; \
+ (void)memset((_s)->private.pvt_pad, 0, sizeof((_s)->private.pvt_pad)); \
+ (void)memset((_s)->__pad, 0, sizeof((_s)->__pad)); \
+} while(0)
+
+#define FRONT_RING_INIT(_r, _s, __size) do { \
+ (_r)->req_prod_pvt = 0; \
+ (_r)->rsp_cons = 0; \
+ (_r)->nr_ents = __RING_SIZE(_s, __size); \
+ (_r)->sring = (_s); \
+} while (0)
+
+#define BACK_RING_INIT(_r, _s, __size) do { \
+ (_r)->rsp_prod_pvt = 0; \
+ (_r)->req_cons = 0; \
+ (_r)->nr_ents = __RING_SIZE(_s, __size); \
+ (_r)->sring = (_s); \
+} while (0)
+
+/* How big is this ring? */
+#define RING_SIZE(_r) \
+ ((_r)->nr_ents)
+
+/* Number of free requests (for use on front side only). */
+#define RING_FREE_REQUESTS(_r) \
+ (RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons))
+
+/* Test if there is an empty slot available on the front ring.
+ * (This is only meaningful from the front. )
+ */
+#define RING_FULL(_r) \
+ (RING_FREE_REQUESTS(_r) == 0)
+
+/* Test if there are outstanding messages to be processed on a ring. */
+#define RING_HAS_UNCONSUMED_RESPONSES(_r) \
+ ((_r)->sring->rsp_prod - (_r)->rsp_cons)
+
+#ifdef __GNUC__
+#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({ \
+ unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \
+ unsigned int rsp = RING_SIZE(_r) - \
+ ((_r)->req_cons - (_r)->rsp_prod_pvt); \
+ req < rsp ? req : rsp; \
+})
+#else
+/* Same as above, but without the nice GCC ({ ... }) syntax. */
+#define RING_HAS_UNCONSUMED_REQUESTS(_r) \
+ ((((_r)->sring->req_prod - (_r)->req_cons) < \
+ (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ? \
+ ((_r)->sring->req_prod - (_r)->req_cons) : \
+ (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt)))
+#endif
+
+/* Direct access to individual ring elements, by index. */
+#define RING_GET_REQUEST(_r, _idx) \
+ (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
+
+#define RING_GET_RESPONSE(_r, _idx) \
+ (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
+
+/* Loop termination condition: Would the specified index overflow the ring? */
+#define RING_REQUEST_CONS_OVERFLOW(_r, _cons) \
+ (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
+
+/* Ill-behaved frontend determination: Can there be this many requests? */
+#define RING_REQUEST_PROD_OVERFLOW(_r, _prod) \
+ (((_prod) - (_r)->rsp_prod_pvt) > RING_SIZE(_r))
+
+#define RING_PUSH_REQUESTS(_r) do { \
+ xen_wmb(); /* back sees requests /before/ updated producer index */ \
+ (_r)->sring->req_prod = (_r)->req_prod_pvt; \
+} while (0)
+
+#define RING_PUSH_RESPONSES(_r) do { \
+ xen_wmb(); /* front sees resps /before/ updated producer index */ \
+ (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt; \
+} while (0)
+
+/*
+ * Notification hold-off (req_event and rsp_event):
+ *
+ * When queueing requests or responses on a shared ring, it may not always be
+ * necessary to notify the remote end. For example, if requests are in flight
+ * in a backend, the front may be able to queue further requests without
+ * notifying the back (if the back checks for new requests when it queues
+ * responses).
+ *
+ * When enqueuing requests or responses:
+ *
+ * Use RING_PUSH_{REQUESTS,RESPONSES}_AND_CHECK_NOTIFY(). The second argument
+ * is a boolean return value. True indicates that the receiver requires an
+ * asynchronous notification.
+ *
+ * After dequeuing requests or responses (before sleeping the connection):
+ *
+ * Use RING_FINAL_CHECK_FOR_REQUESTS() or RING_FINAL_CHECK_FOR_RESPONSES().
+ * The second argument is a boolean return value. True indicates that there
+ * are pending messages on the ring (i.e., the connection should not be put
+ * to sleep).
+ *
+ * These macros will set the req_event/rsp_event field to trigger a
+ * notification on the very next message that is enqueued. If you want to
+ * create batches of work (i.e., only receive a notification after several
+ * messages have been enqueued) then you will need to create a customised
+ * version of the FINAL_CHECK macro in your own code, which sets the event
+ * field appropriately.
+ */
+
+#define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do { \
+ RING_IDX __old = (_r)->sring->req_prod; \
+ RING_IDX __new = (_r)->req_prod_pvt; \
+ xen_wmb(); /* back sees requests /before/ updated producer index */ \
+ (_r)->sring->req_prod = __new; \
+ xen_mb(); /* back sees new requests /before/ we check req_event */ \
+ (_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) < \
+ (RING_IDX)(__new - __old)); \
+} while (0)
+
+#define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do { \
+ RING_IDX __old = (_r)->sring->rsp_prod; \
+ RING_IDX __new = (_r)->rsp_prod_pvt; \
+ xen_wmb(); /* front sees resps /before/ updated producer index */ \
+ (_r)->sring->rsp_prod = __new; \
+ xen_mb(); /* front sees new resps /before/ we check rsp_event */ \
+ (_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) < \
+ (RING_IDX)(__new - __old)); \
+} while (0)
+
+#define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do { \
+ (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
+ if (_work_to_do) break; \
+ (_r)->sring->req_event = (_r)->req_cons + 1; \
+ xen_mb(); \
+ (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
+} while (0)
+
+#define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do { \
+ (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
+ if (_work_to_do) break; \
+ (_r)->sring->rsp_event = (_r)->rsp_cons + 1; \
+ xen_mb(); \
+ (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
+} while (0)
+
+#endif /* __XEN_PUBLIC_IO_RING_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * tpmif.h
+ *
+ * TPM I/O interface for Xen guest OSes.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@us.ibm.com
+ * Grant table support: Mahadevan Gomathisankaran
+ *
+ * This code has been derived from tools/libxc/xen/io/netif.h
+ *
+ * Copyright (c) 2003-2004, Keir Fraser
+ */
+
+#ifndef __XEN_PUBLIC_IO_TPMIF_H__
+#define __XEN_PUBLIC_IO_TPMIF_H__
+
+#include "../grant_table.h"
+
+struct tpmif_tx_request {
+ unsigned long addr; /* Machine address of packet. */
+ grant_ref_t ref; /* grant table access reference */
+ uint16_t unused;
+ uint16_t size; /* Packet size in bytes. */
+};
+typedef struct tpmif_tx_request tpmif_tx_request_t;
+
+/*
+ * The TPMIF_TX_RING_SIZE defines the number of pages the
+ * front-end and backend can exchange (= size of array).
+ */
+typedef uint32_t TPMIF_RING_IDX;
+
+#define TPMIF_TX_RING_SIZE 1
+
+/* This structure must fit in a memory page. */
+
+struct tpmif_ring {
+ struct tpmif_tx_request req;
+};
+typedef struct tpmif_ring tpmif_ring_t;
+
+struct tpmif_tx_interface {
+ struct tpmif_ring ring[TPMIF_TX_RING_SIZE];
+};
+typedef struct tpmif_tx_interface tpmif_tx_interface_t;
+
+/******************************************************************************
+ * TPM I/O interface for Xen guest OSes, v2
+ *
+ * Author: Daniel De Graaf <dgdegra@tycho.nsa.gov>
+ *
+ * This protocol emulates the request/response behavior of a TPM using a Xen
+ * shared memory interface. All interaction with the TPM is at the direction
+ * of the frontend, since a TPM (hardware or virtual) is a passive device -
+ * the backend only processes commands as requested by the frontend.
+ *
+ * The frontend sends a request to the TPM by populating the shared page with
+ * the request packet, changing the state to TPMIF_STATE_SUBMIT, and sending
+ * and event channel notification. When the backend is finished, it will set
+ * the state to TPMIF_STATE_FINISH and send an event channel notification.
+ *
+ * In order to allow long-running commands to be canceled, the frontend can
+ * at any time change the state to TPMIF_STATE_CANCEL and send a notification.
+ * The TPM can either finish the command (changing state to TPMIF_STATE_FINISH)
+ * or can cancel the command and change the state to TPMIF_STATE_IDLE. The TPM
+ * can also change the state to TPMIF_STATE_IDLE instead of TPMIF_STATE_FINISH
+ * if another reason for cancellation is required - for example, a physical
+ * TPM may cancel a command if the interface is seized by another locality.
+ *
+ * The TPM command format is defined by the TCG, and is available at
+ * http://www.trustedcomputinggroup.org/resources/tpm_main_specification
+ */
+
+enum tpmif_state {
+ TPMIF_STATE_IDLE, /* no contents / vTPM idle / cancel complete */
+ TPMIF_STATE_SUBMIT, /* request ready / vTPM working */
+ TPMIF_STATE_FINISH, /* response ready / vTPM idle */
+ TPMIF_STATE_CANCEL, /* cancel requested / vTPM working */
+};
+/* Note: The backend should only change state to IDLE or FINISH, while the
+ * frontend should only change to SUBMIT or CANCEL. Status changes do not need
+ * to use atomic operations.
+ */
+
+
+/* The shared page for vTPM request/response packets looks like:
+ *
+ * Offset Contents
+ * =================================================
+ * 0 struct tpmif_shared_page
+ * 16 [optional] List of grant IDs
+ * 16+4*nr_extra_pages TPM packet data
+ *
+ * If the TPM packet data extends beyond the end of a single page, the grant IDs
+ * defined in extra_pages are used as if they were mapped immediately following
+ * the primary shared page. The grants are allocated by the frontend and mapped
+ * by the backend. Before sending a request spanning multiple pages, the
+ * frontend should verify that the TPM supports such large requests by querying
+ * the TPM_CAP_PROP_INPUT_BUFFER property from the TPM.
+ */
+struct tpmif_shared_page {
+ uint32_t length; /* request/response length in bytes */
+
+ uint8_t state; /* enum tpmif_state */
+ uint8_t locality; /* for the current request */
+ uint8_t pad; /* should be zero */
+
+ uint8_t nr_extra_pages; /* extra pages for long packets; may be zero */
+ uint32_t extra_pages[0]; /* grant IDs; length is actually nr_extra_pages */
+};
+typedef struct tpmif_shared_page tpmif_shared_page_t;
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/*
+ * usbif.h
+ *
+ * USB I/O interface for Xen guest OSes.
+ *
+ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PUBLIC_IO_USBIF_H__
+#define __XEN_PUBLIC_IO_USBIF_H__
+
+#include "ring.h"
+#include "../grant_table.h"
+
+enum usb_spec_version {
+ USB_VER_UNKNOWN = 0,
+ USB_VER_USB11,
+ USB_VER_USB20,
+ USB_VER_USB30, /* not supported yet */
+};
+
+/*
+ * USB pipe in usbif_request
+ *
+ * bits 0-5 are specific bits for virtual USB driver.
+ * bits 7-31 are standard urb pipe.
+ *
+ * - port number(NEW): bits 0-4
+ * (USB_MAXCHILDREN is 31)
+ *
+ * - operation flag(NEW): bit 5
+ * (0 = submit urb,
+ * 1 = unlink urb)
+ *
+ * - direction: bit 7
+ * (0 = Host-to-Device [Out]
+ * 1 = Device-to-Host [In])
+ *
+ * - device address: bits 8-14
+ *
+ * - endpoint: bits 15-18
+ *
+ * - pipe type: bits 30-31
+ * (00 = isochronous, 01 = interrupt,
+ * 10 = control, 11 = bulk)
+ */
+#define usbif_pipeportnum(pipe) ((pipe) & 0x1f)
+#define usbif_setportnum_pipe(pipe, portnum) \
+ ((pipe)|(portnum))
+
+#define usbif_pipeunlink(pipe) ((pipe) & 0x20)
+#define usbif_pipesubmit(pipe) (!usbif_pipeunlink(pipe))
+#define usbif_setunlink_pipe(pipe) ((pipe)|(0x20))
+
+#define USBIF_MAX_SEGMENTS_PER_REQUEST (16)
+
+/*
+ * RING for transferring urbs.
+ */
+struct usbif_request_segment {
+ grant_ref_t gref;
+ uint16_t offset;
+ uint16_t length;
+};
+
+struct usbif_urb_request {
+ uint16_t id; /* request id */
+ uint16_t nr_buffer_segs; /* number of urb->transfer_buffer segments */
+
+ /* basic urb parameter */
+ uint32_t pipe;
+ uint16_t transfer_flags;
+ uint16_t buffer_length;
+ union {
+ uint8_t ctrl[8]; /* setup_packet (Ctrl) */
+
+ struct {
+ uint16_t interval; /* maximum (1024*8) in usb core */
+ uint16_t start_frame; /* start frame */
+ uint16_t number_of_packets; /* number of ISO packet */
+ uint16_t nr_frame_desc_segs; /* number of iso_frame_desc segments */
+ } isoc;
+
+ struct {
+ uint16_t interval; /* maximum (1024*8) in usb core */
+ uint16_t pad[3];
+ } intr;
+
+ struct {
+ uint16_t unlink_id; /* unlink request id */
+ uint16_t pad[3];
+ } unlink;
+
+ } u;
+
+ /* urb data segments */
+ struct usbif_request_segment seg[USBIF_MAX_SEGMENTS_PER_REQUEST];
+};
+typedef struct usbif_urb_request usbif_urb_request_t;
+
+struct usbif_urb_response {
+ uint16_t id; /* request id */
+ uint16_t start_frame; /* start frame (ISO) */
+ int32_t status; /* status (non-ISO) */
+ int32_t actual_length; /* actual transfer length */
+ int32_t error_count; /* number of ISO errors */
+};
+typedef struct usbif_urb_response usbif_urb_response_t;
+
+DEFINE_RING_TYPES(usbif_urb, struct usbif_urb_request, struct usbif_urb_response);
+#define USB_URB_RING_SIZE __CONST_RING_SIZE(usbif_urb, PAGE_SIZE)
+
+/*
+ * RING for notifying connect/disconnect events to frontend
+ */
+struct usbif_conn_request {
+ uint16_t id;
+};
+typedef struct usbif_conn_request usbif_conn_request_t;
+
+struct usbif_conn_response {
+ uint16_t id; /* request id */
+ uint8_t portnum; /* port number */
+ uint8_t speed; /* usb_device_speed */
+};
+typedef struct usbif_conn_response usbif_conn_response_t;
+
+DEFINE_RING_TYPES(usbif_conn, struct usbif_conn_request, struct usbif_conn_response);
+#define USB_CONN_RING_SIZE __CONST_RING_SIZE(usbif_conn, PAGE_SIZE)
+
+#endif /* __XEN_PUBLIC_IO_USBIF_H__ */
--- /dev/null
+/******************************************************************************
+ * vscsiif.h
+ *
+ * Based on the blkif.h code.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright(c) FUJITSU Limited 2008.
+ */
+
+#ifndef __XEN__PUBLIC_IO_SCSI_H__
+#define __XEN__PUBLIC_IO_SCSI_H__
+
+#include "ring.h"
+#include "../grant_table.h"
+
+/*
+ * Feature and Parameter Negotiation
+ * =================================
+ * The two halves of a Xen pvSCSI driver utilize nodes within the XenStore to
+ * communicate capabilities and to negotiate operating parameters. This
+ * section enumerates these nodes which reside in the respective front and
+ * backend portions of the XenStore, following the XenBus convention.
+ *
+ * Any specified default value is in effect if the corresponding XenBus node
+ * is not present in the XenStore.
+ *
+ * XenStore nodes in sections marked "PRIVATE" are solely for use by the
+ * driver side whose XenBus tree contains them.
+ *
+ *****************************************************************************
+ * Backend XenBus Nodes
+ *****************************************************************************
+ *
+ *------------------ Backend Device Identification (PRIVATE) ------------------
+ *
+ * p-devname
+ * Values: string
+ *
+ * A free string used to identify the physical device (e.g. a disk name).
+ *
+ * p-dev
+ * Values: string
+ *
+ * A string specifying the backend device: either a 4-tuple "h:c:t:l"
+ * (host, controller, target, lun, all integers), or a WWN (e.g.
+ * "naa.60014054ac780582").
+ *
+ * v-dev
+ * Values: string
+ *
+ * A string specifying the frontend device in form of a 4-tuple "h:c:t:l"
+ * (host, controller, target, lun, all integers).
+ *
+ *--------------------------------- Features ---------------------------------
+ *
+ * feature-sg-grant
+ * Values: unsigned [VSCSIIF_SG_TABLESIZE...65535]
+ * Default Value: 0
+ *
+ * Specifies the maximum number of scatter/gather elements in grant pages
+ * supported. If not set, the backend supports up to VSCSIIF_SG_TABLESIZE
+ * SG elements specified directly in the request.
+ *
+ *****************************************************************************
+ * Frontend XenBus Nodes
+ *****************************************************************************
+ *
+ *----------------------- Request Transport Parameters -----------------------
+ *
+ * event-channel
+ * Values: unsigned
+ *
+ * The identifier of the Xen event channel used to signal activity
+ * in the ring buffer.
+ *
+ * ring-ref
+ * Values: unsigned
+ *
+ * The Xen grant reference granting permission for the backend to map
+ * the sole page in a single page sized ring buffer.
+ *
+ * protocol
+ * Values: string (XEN_IO_PROTO_ABI_*)
+ * Default Value: XEN_IO_PROTO_ABI_NATIVE
+ *
+ * The machine ABI rules governing the format of all ring request and
+ * response structures.
+ */
+
+/* Requests from the frontend to the backend */
+
+/*
+ * Request a SCSI operation specified via a CDB in vscsiif_request.cmnd.
+ * The target is specified via channel, id and lun.
+ *
+ * The operation to be performed is specified via a CDB in cmnd[], the length
+ * of the CDB is in cmd_len. sc_data_direction specifies the direction of data
+ * (to the device, from the device, or none at all).
+ *
+ * If data is to be transferred to or from the device the buffer(s) in the
+ * guest memory is/are specified via one or multiple scsiif_request_segment
+ * descriptors each specifying a memory page via a grant_ref_t, a offset into
+ * the page and the length of the area in that page. All scsiif_request_segment
+ * areas concatenated form the resulting data buffer used by the operation.
+ * If the number of scsiif_request_segment areas is not too large (less than
+ * or equal VSCSIIF_SG_TABLESIZE) the areas can be specified directly in the
+ * seg[] array and the number of valid scsiif_request_segment elements is to be
+ * set in nr_segments.
+ *
+ * If "feature-sg-grant" in the Xenstore is set it is possible to specify more
+ * than VSCSIIF_SG_TABLESIZE scsiif_request_segment elements via indirection.
+ * The maximum number of allowed scsiif_request_segment elements is the value
+ * of the "feature-sg-grant" entry from Xenstore. When using indirection the
+ * seg[] array doesn't contain specifications of the data buffers, but
+ * references to scsiif_request_segment arrays, which in turn reference the
+ * data buffers. While nr_segments holds the number of populated seg[] entries
+ * (plus the set VSCSIIF_SG_GRANT bit), the number of scsiif_request_segment
+ * elements referencing the target data buffers is calculated from the lengths
+ * of the seg[] elements (the sum of all valid seg[].length divided by the
+ * size of one scsiif_request_segment structure). The frontend may use a mix of
+ * direct and indirect requests.
+ */
+#define VSCSIIF_ACT_SCSI_CDB 1
+
+/*
+ * Request abort of a running operation for the specified target given by
+ * channel, id, lun and the operation's rqid in ref_rqid.
+ */
+#define VSCSIIF_ACT_SCSI_ABORT 2
+
+/*
+ * Request a device reset of the specified target (channel and id).
+ */
+#define VSCSIIF_ACT_SCSI_RESET 3
+
+/*
+ * Preset scatter/gather elements for a following request. Deprecated.
+ * Keeping the define only to avoid usage of the value "4" for other actions.
+ */
+#define VSCSIIF_ACT_SCSI_SG_PRESET 4
+
+/*
+ * Maximum scatter/gather segments per request.
+ *
+ * Considering balance between allocating at least 16 "vscsiif_request"
+ * structures on one page (4096 bytes) and the number of scatter/gather
+ * elements needed, we decided to use 26 as a magic number.
+ *
+ * If "feature-sg-grant" is set, more scatter/gather elements can be specified
+ * by placing them in one or more (up to VSCSIIF_SG_TABLESIZE) granted pages.
+ * In this case the vscsiif_request seg elements don't contain references to
+ * the user data, but to the SG elements referencing the user data.
+ */
+#define VSCSIIF_SG_TABLESIZE 26
+
+/*
+ * based on Linux kernel 2.6.18, still valid
+ *
+ * Changing these values requires support of multiple protocols via the rings
+ * as "old clients" will blindly use these values and the resulting structure
+ * sizes.
+ */
+#define VSCSIIF_MAX_COMMAND_SIZE 16
+#define VSCSIIF_SENSE_BUFFERSIZE 96
+
+struct scsiif_request_segment {
+ grant_ref_t gref;
+ uint16_t offset;
+ uint16_t length;
+};
+typedef struct scsiif_request_segment vscsiif_segment_t;
+
+#define VSCSIIF_SG_PER_PAGE (PAGE_SIZE / sizeof(struct scsiif_request_segment))
+
+/* Size of one request is 252 bytes */
+struct vscsiif_request {
+ uint16_t rqid; /* private guest value, echoed in resp */
+ uint8_t act; /* command between backend and frontend */
+ uint8_t cmd_len; /* valid CDB bytes */
+
+ uint8_t cmnd[VSCSIIF_MAX_COMMAND_SIZE]; /* the CDB */
+ uint16_t timeout_per_command; /* deprecated: timeout in secs, 0=default */
+ uint16_t channel, id, lun; /* (virtual) device specification */
+ uint16_t ref_rqid; /* command abort reference */
+ uint8_t sc_data_direction; /* for DMA_TO_DEVICE(1)
+ DMA_FROM_DEVICE(2)
+ DMA_NONE(3) requests */
+ uint8_t nr_segments; /* Number of pieces of scatter-gather */
+/*
+ * flag in nr_segments: SG elements via grant page
+ *
+ * If VSCSIIF_SG_GRANT is set, the low 7 bits of nr_segments specify the number
+ * of grant pages containing SG elements. Usable if "feature-sg-grant" set.
+ */
+#define VSCSIIF_SG_GRANT 0x80
+
+ vscsiif_segment_t seg[VSCSIIF_SG_TABLESIZE];
+ uint32_t reserved[3];
+};
+typedef struct vscsiif_request vscsiif_request_t;
+
+/*
+ * The following interface is deprecated!
+ */
+#define VSCSIIF_SG_LIST_SIZE ((sizeof(vscsiif_request_t) - 4) \
+ / sizeof(vscsiif_segment_t))
+
+struct vscsiif_sg_list {
+ /* First two fields must match struct vscsiif_request! */
+ uint16_t rqid; /* private guest value, must match main req */
+ uint8_t act; /* VSCSIIF_ACT_SCSI_SG_PRESET */
+ uint8_t nr_segments; /* Number of pieces of scatter-gather */
+ vscsiif_segment_t seg[VSCSIIF_SG_LIST_SIZE];
+};
+typedef struct vscsiif_sg_list vscsiif_sg_list_t;
+/* End of deprecated interface */
+
+/* Size of one response is 252 bytes */
+struct vscsiif_response {
+ uint16_t rqid; /* identifies request */
+ uint8_t act; /* deprecated: valid only if SG_PRESET supported */
+ uint8_t sense_len;
+ uint8_t sense_buffer[VSCSIIF_SENSE_BUFFERSIZE];
+ int32_t rslt;
+ uint32_t residual_len; /* request bufflen -
+ return the value from physical device */
+ uint32_t reserved[36];
+};
+typedef struct vscsiif_response vscsiif_response_t;
+
+DEFINE_RING_TYPES(vscsiif, struct vscsiif_request, struct vscsiif_response);
+
+
+#endif /*__XEN__PUBLIC_IO_SCSI_H__*/
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/*****************************************************************************
+ * xenbus.h
+ *
+ * Xenbus protocol details.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (C) 2005 XenSource Ltd.
+ */
+
+#ifndef _XEN_PUBLIC_IO_XENBUS_H
+#define _XEN_PUBLIC_IO_XENBUS_H
+
+/*
+ * The state of either end of the Xenbus, i.e. the current communication
+ * status of initialisation across the bus. States here imply nothing about
+ * the state of the connection between the driver and the kernel's device
+ * layers.
+ */
+enum xenbus_state {
+ XenbusStateUnknown = 0,
+
+ XenbusStateInitialising = 1,
+
+ /*
+ * InitWait: Finished early initialisation but waiting for information
+ * from the peer or hotplug scripts.
+ */
+ XenbusStateInitWait = 2,
+
+ /*
+ * Initialised: Waiting for a connection from the peer.
+ */
+ XenbusStateInitialised = 3,
+
+ XenbusStateConnected = 4,
+
+ /*
+ * Closing: The device is being closed due to an error or an unplug event.
+ */
+ XenbusStateClosing = 5,
+
+ XenbusStateClosed = 6,
+
+ /*
+ * Reconfiguring: The device is being reconfigured.
+ */
+ XenbusStateReconfiguring = 7,
+
+ XenbusStateReconfigured = 8
+};
+typedef enum xenbus_state XenbusState;
+
+#endif /* _XEN_PUBLIC_IO_XENBUS_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/*
+ * Details of the "wire" protocol between Xen Store Daemon and client
+ * library or guest kernel.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (C) 2005 Rusty Russell IBM Corporation
+ */
+
+#ifndef _XS_WIRE_H
+#define _XS_WIRE_H
+
+enum xsd_sockmsg_type
+{
+ XS_DEBUG,
+ XS_DIRECTORY,
+ XS_READ,
+ XS_GET_PERMS,
+ XS_WATCH,
+ XS_UNWATCH,
+ XS_TRANSACTION_START,
+ XS_TRANSACTION_END,
+ XS_INTRODUCE,
+ XS_RELEASE,
+ XS_GET_DOMAIN_PATH,
+ XS_WRITE,
+ XS_MKDIR,
+ XS_RM,
+ XS_SET_PERMS,
+ XS_WATCH_EVENT,
+ XS_ERROR,
+ XS_IS_DOMAIN_INTRODUCED,
+ XS_RESUME,
+ XS_SET_TARGET,
+ XS_RESTRICT,
+ XS_RESET_WATCHES,
+
+ XS_INVALID = 0xffff /* Guaranteed to remain an invalid type */
+};
+
+#define XS_WRITE_NONE "NONE"
+#define XS_WRITE_CREATE "CREATE"
+#define XS_WRITE_CREATE_EXCL "CREATE|EXCL"
+
+/* We hand errors as strings, for portability. */
+struct xsd_errors
+{
+ int errnum;
+ const char *errstring;
+};
+#ifdef EINVAL
+#define XSD_ERROR(x) { x, #x }
+/* LINTED: static unused */
+static struct xsd_errors xsd_errors[]
+#if defined(__GNUC__)
+__attribute__((unused))
+#endif
+ = {
+ XSD_ERROR(EINVAL),
+ XSD_ERROR(EACCES),
+ XSD_ERROR(EEXIST),
+ XSD_ERROR(EISDIR),
+ XSD_ERROR(ENOENT),
+ XSD_ERROR(ENOMEM),
+ XSD_ERROR(ENOSPC),
+ XSD_ERROR(EIO),
+ XSD_ERROR(ENOTEMPTY),
+ XSD_ERROR(ENOSYS),
+ XSD_ERROR(EROFS),
+ XSD_ERROR(EBUSY),
+ XSD_ERROR(EAGAIN),
+ XSD_ERROR(EISCONN),
+ XSD_ERROR(E2BIG)
+};
+#endif
+
+struct xsd_sockmsg
+{
+ uint32_t type; /* XS_??? */
+ uint32_t req_id;/* Request identifier, echoed in daemon's response. */
+ uint32_t tx_id; /* Transaction id (0 if not related to a transaction). */
+ uint32_t len; /* Length of data following this. */
+
+ /* Generally followed by nul-terminated string(s). */
+};
+
+enum xs_watch_type
+{
+ XS_WATCH_PATH = 0,
+ XS_WATCH_TOKEN
+};
+
+/*
+ * `incontents 150 xenstore_struct XenStore wire protocol.
+ *
+ * Inter-domain shared memory communications. */
+#define XENSTORE_RING_SIZE 1024
+typedef uint32_t XENSTORE_RING_IDX;
+#define MASK_XENSTORE_IDX(idx) ((idx) & (XENSTORE_RING_SIZE-1))
+struct xenstore_domain_interface {
+ char req[XENSTORE_RING_SIZE]; /* Requests to xenstore daemon. */
+ char rsp[XENSTORE_RING_SIZE]; /* Replies and async watch events. */
+ XENSTORE_RING_IDX req_cons, req_prod;
+ XENSTORE_RING_IDX rsp_cons, rsp_prod;
+ uint32_t server_features; /* Bitmap of features supported by the server */
+ uint32_t connection;
+};
+
+/* Violating this is very bad. See docs/misc/xenstore.txt. */
+#define XENSTORE_PAYLOAD_MAX 4096
+
+/* Violating these just gets you an error back */
+#define XENSTORE_ABS_PATH_MAX 3072
+#define XENSTORE_REL_PATH_MAX 2048
+
+/* The ability to reconnect a ring */
+#define XENSTORE_SERVER_FEATURE_RECONNECTION 1
+
+/* Valid values for the connection field */
+#define XENSTORE_CONNECTED 0 /* the steady-state */
+#define XENSTORE_RECONNECT 1 /* guest has initiated a reconnect */
+
+#endif /* _XS_WIRE_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * kexec.h - Public portion
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Xen port written by:
+ * - Simon 'Horms' Horman <horms@verge.net.au>
+ * - Magnus Damm <magnus@valinux.co.jp>
+ */
+
+#ifndef _XEN_PUBLIC_KEXEC_H
+#define _XEN_PUBLIC_KEXEC_H
+
+
+/* This file describes the Kexec / Kdump hypercall interface for Xen.
+ *
+ * Kexec under vanilla Linux allows a user to reboot the physical machine
+ * into a new user-specified kernel. The Xen port extends this idea
+ * to allow rebooting of the machine from dom0. When kexec for dom0
+ * is used to reboot, both the hypervisor and the domains get replaced
+ * with some other kernel. It is possible to kexec between vanilla
+ * Linux and Xen and back again. Xen to Xen works well too.
+ *
+ * The hypercall interface for kexec can be divided into three main
+ * types of hypercall operations:
+ *
+ * 1) Range information:
+ * This is used by the dom0 kernel to ask the hypervisor about various
+ * address information. This information is needed to allow kexec-tools
+ * to fill in the ELF headers for /proc/vmcore properly.
+ *
+ * 2) Load and unload of images:
+ * There are no big surprises here, the kexec binary from kexec-tools
+ * runs in userspace in dom0. The tool loads/unloads data into the
+ * dom0 kernel such as new kernel, initramfs and hypervisor. When
+ * loaded the dom0 kernel performs a load hypercall operation, and
+ * before releasing all page references the dom0 kernel calls unload.
+ *
+ * 3) Kexec operation:
+ * This is used to start a previously loaded kernel.
+ */
+
+#include "xen.h"
+
+#if defined(__i386__) || defined(__x86_64__)
+#define KEXEC_XEN_NO_PAGES 17
+#endif
+
+/*
+ * Prototype for this hypercall is:
+ * int kexec_op(int cmd, void *args)
+ * @cmd == KEXEC_CMD_...
+ * KEXEC operation to perform
+ * @args == Operation-specific extra arguments (NULL if none).
+ */
+
+/*
+ * Kexec supports two types of operation:
+ * - kexec into a regular kernel, very similar to a standard reboot
+ * - KEXEC_TYPE_DEFAULT is used to specify this type
+ * - kexec into a special "crash kernel", aka kexec-on-panic
+ * - KEXEC_TYPE_CRASH is used to specify this type
+ * - parts of our system may be broken at kexec-on-panic time
+ * - the code should be kept as simple and self-contained as possible
+ */
+
+#define KEXEC_TYPE_DEFAULT 0
+#define KEXEC_TYPE_CRASH 1
+
+
+/* The kexec implementation for Xen allows the user to load two
+ * types of kernels, KEXEC_TYPE_DEFAULT and KEXEC_TYPE_CRASH.
+ * All data needed for a kexec reboot is kept in one xen_kexec_image_t
+ * per "instance". The data mainly consists of machine address lists to pages
+ * together with destination addresses. The data in xen_kexec_image_t
+ * is passed to the "code page" which is one page of code that performs
+ * the final relocations before jumping to the new kernel.
+ */
+
+typedef struct xen_kexec_image {
+#if defined(__i386__) || defined(__x86_64__)
+ unsigned long page_list[KEXEC_XEN_NO_PAGES];
+#endif
+ unsigned long indirection_page;
+ unsigned long start_address;
+} xen_kexec_image_t;
+
+/*
+ * Perform kexec having previously loaded a kexec or kdump kernel
+ * as appropriate.
+ * type == KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH [in]
+ *
+ * Control is transferred to the image entry point with the host in
+ * the following state.
+ *
+ * - The image may be executed on any PCPU and all other PCPUs are
+ * stopped.
+ *
+ * - Local interrupts are disabled.
+ *
+ * - Register values are undefined.
+ *
+ * - The image segments have writeable 1:1 virtual to machine
+ * mappings. The location of any page tables is undefined and these
+ * page table frames are not be mapped.
+ */
+#define KEXEC_CMD_kexec 0
+typedef struct xen_kexec_exec {
+ int type;
+} xen_kexec_exec_t;
+
+/*
+ * Load/Unload kernel image for kexec or kdump.
+ * type == KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH [in]
+ * image == relocation information for kexec (ignored for unload) [in]
+ */
+#define KEXEC_CMD_kexec_load_v1 1 /* obsolete since 0x00040400 */
+#define KEXEC_CMD_kexec_unload_v1 2 /* obsolete since 0x00040400 */
+typedef struct xen_kexec_load_v1 {
+ int type;
+ xen_kexec_image_t image;
+} xen_kexec_load_v1_t;
+
+#define KEXEC_RANGE_MA_CRASH 0 /* machine address and size of crash area */
+#define KEXEC_RANGE_MA_XEN 1 /* machine address and size of Xen itself */
+#define KEXEC_RANGE_MA_CPU 2 /* machine address and size of a CPU note */
+#define KEXEC_RANGE_MA_XENHEAP 3 /* machine address and size of xenheap
+ * Note that although this is adjacent
+ * to Xen it exists in a separate EFI
+ * region on ia64, and thus needs to be
+ * inserted into iomem_machine separately */
+#define KEXEC_RANGE_MA_BOOT_PARAM 4 /* Obsolete: machine address and size of
+ * the ia64_boot_param */
+#define KEXEC_RANGE_MA_EFI_MEMMAP 5 /* machine address and size of
+ * of the EFI Memory Map */
+#define KEXEC_RANGE_MA_VMCOREINFO 6 /* machine address and size of vmcoreinfo */
+
+/*
+ * Find the address and size of certain memory areas
+ * range == KEXEC_RANGE_... [in]
+ * nr == physical CPU number (starting from 0) if KEXEC_RANGE_MA_CPU [in]
+ * size == number of bytes reserved in window [out]
+ * start == address of the first byte in the window [out]
+ */
+#define KEXEC_CMD_kexec_get_range 3
+typedef struct xen_kexec_range {
+ int range;
+ int nr;
+ unsigned long size;
+ unsigned long start;
+} xen_kexec_range_t;
+
+#if __XEN_INTERFACE_VERSION__ >= 0x00040400
+/*
+ * A contiguous chunk of a kexec image and it's destination machine
+ * address.
+ */
+typedef struct xen_kexec_segment {
+ union {
+ XEN_GUEST_HANDLE(const_void) h;
+ uint64_t _pad;
+ } buf;
+ uint64_t buf_size;
+ uint64_t dest_maddr;
+ uint64_t dest_size;
+} xen_kexec_segment_t;
+DEFINE_XEN_GUEST_HANDLE(xen_kexec_segment_t);
+
+/*
+ * Load a kexec image into memory.
+ *
+ * For KEXEC_TYPE_DEFAULT images, the segments may be anywhere in RAM.
+ * The image is relocated prior to being executed.
+ *
+ * For KEXEC_TYPE_CRASH images, each segment of the image must reside
+ * in the memory region reserved for kexec (KEXEC_RANGE_MA_CRASH) and
+ * the entry point must be within the image. The caller is responsible
+ * for ensuring that multiple images do not overlap.
+ *
+ * All image segments will be loaded to their destination machine
+ * addresses prior to being executed. The trailing portion of any
+ * segments with a source buffer (from dest_maddr + buf_size to
+ * dest_maddr + dest_size) will be zeroed.
+ *
+ * Segments with no source buffer will be accessible to the image when
+ * it is executed.
+ */
+
+#define KEXEC_CMD_kexec_load 4
+typedef struct xen_kexec_load {
+ uint8_t type; /* One of KEXEC_TYPE_* */
+ uint8_t _pad;
+ uint16_t arch; /* ELF machine type (EM_*). */
+ uint32_t nr_segments;
+ union {
+ XEN_GUEST_HANDLE(xen_kexec_segment_t) h;
+ uint64_t _pad;
+ } segments;
+ uint64_t entry_maddr; /* image entry point machine address. */
+} xen_kexec_load_t;
+DEFINE_XEN_GUEST_HANDLE(xen_kexec_load_t);
+
+/*
+ * Unload a kexec image.
+ *
+ * Type must be one of KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH.
+ */
+#define KEXEC_CMD_kexec_unload 5
+typedef struct xen_kexec_unload {
+ uint8_t type;
+} xen_kexec_unload_t;
+DEFINE_XEN_GUEST_HANDLE(xen_kexec_unload_t);
+
+#else /* __XEN_INTERFACE_VERSION__ < 0x00040400 */
+
+#define KEXEC_CMD_kexec_load KEXEC_CMD_kexec_load_v1
+#define KEXEC_CMD_kexec_unload KEXEC_CMD_kexec_unload_v1
+#define xen_kexec_load xen_kexec_load_v1
+#define xen_kexec_load_t xen_kexec_load_v1_t
+
+#endif
+
+#endif /* _XEN_PUBLIC_KEXEC_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * mem_event.h
+ *
+ * Memory event common structures.
+ *
+ * Copyright (c) 2009 by Citrix Systems, Inc. (Patrick Colp)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _XEN_PUBLIC_MEM_EVENT_H
+#define _XEN_PUBLIC_MEM_EVENT_H
+
+#include "xen.h"
+#include "io/ring.h"
+
+/* Memory event flags */
+#define MEM_EVENT_FLAG_VCPU_PAUSED (1 << 0)
+#define MEM_EVENT_FLAG_DROP_PAGE (1 << 1)
+#define MEM_EVENT_FLAG_EVICT_FAIL (1 << 2)
+#define MEM_EVENT_FLAG_FOREIGN (1 << 3)
+#define MEM_EVENT_FLAG_DUMMY (1 << 4)
+/*
+ * Emulate the fault-causing instruction (if set in the event response flags).
+ * This will allow the guest to continue execution without lifting the page
+ * access restrictions.
+ */
+#define MEM_EVENT_FLAG_EMULATE (1 << 5)
+/*
+ * Same as MEM_EVENT_FLAG_EMULATE, but with write operations or operations
+ * potentially having side effects (like memory mapped or port I/O) disabled.
+ */
+#define MEM_EVENT_FLAG_EMULATE_NOWRITE (1 << 6)
+
+/* Reasons for the memory event request */
+#define MEM_EVENT_REASON_UNKNOWN 0 /* typical reason */
+#define MEM_EVENT_REASON_VIOLATION 1 /* access violation, GFN is address */
+#define MEM_EVENT_REASON_CR0 2 /* CR0 was hit: gfn is new CR0 value, gla is previous */
+#define MEM_EVENT_REASON_CR3 3 /* CR3 was hit: gfn is new CR3 value, gla is previous */
+#define MEM_EVENT_REASON_CR4 4 /* CR4 was hit: gfn is new CR4 value, gla is previous */
+#define MEM_EVENT_REASON_INT3 5 /* int3 was hit: gla/gfn are RIP */
+#define MEM_EVENT_REASON_SINGLESTEP 6 /* single step was invoked: gla/gfn are RIP */
+#define MEM_EVENT_REASON_MSR 7 /* MSR was hit: gfn is MSR value, gla is MSR address;
+ does NOT honour HVMPME_onchangeonly */
+
+/* Using a custom struct (not hvm_hw_cpu) so as to not fill
+ * the mem_event ring buffer too quickly. */
+struct mem_event_regs_x86 {
+ uint64_t rax;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rbx;
+ uint64_t rsp;
+ uint64_t rbp;
+ uint64_t rsi;
+ uint64_t rdi;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ uint64_t rflags;
+ uint64_t dr7;
+ uint64_t rip;
+ uint64_t cr0;
+ uint64_t cr2;
+ uint64_t cr3;
+ uint64_t cr4;
+ uint64_t sysenter_cs;
+ uint64_t sysenter_esp;
+ uint64_t sysenter_eip;
+ uint64_t msr_efer;
+ uint64_t msr_star;
+ uint64_t msr_lstar;
+ uint64_t fs_base;
+ uint64_t gs_base;
+ uint32_t cs_arbytes;
+ uint32_t _pad;
+};
+
+typedef struct mem_event_st {
+ uint32_t flags;
+ uint32_t vcpu_id;
+
+ uint64_t gfn;
+ uint64_t offset;
+ uint64_t gla; /* if gla_valid */
+
+ uint32_t p2mt;
+
+ uint16_t access_r:1;
+ uint16_t access_w:1;
+ uint16_t access_x:1;
+ uint16_t gla_valid:1;
+ uint16_t fault_with_gla:1;
+ uint16_t fault_in_gpt:1;
+ uint16_t available:10;
+
+ uint16_t reason;
+ struct mem_event_regs_x86 x86_regs;
+} mem_event_request_t, mem_event_response_t;
+
+DEFINE_RING_TYPES(mem_event, mem_event_request_t, mem_event_response_t);
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * memory.h
+ *
+ * Memory reservation and information.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
+ */
+
+#ifndef __XEN_PUBLIC_MEMORY_H__
+#define __XEN_PUBLIC_MEMORY_H__
+
+#include "xen.h"
+
+/*
+ * Increase or decrease the specified domain's memory reservation. Returns the
+ * number of extents successfully allocated or freed.
+ * arg == addr of struct xen_memory_reservation.
+ */
+#define XENMEM_increase_reservation 0
+#define XENMEM_decrease_reservation 1
+#define XENMEM_populate_physmap 6
+
+#if __XEN_INTERFACE_VERSION__ >= 0x00030209
+/*
+ * Maximum # bits addressable by the user of the allocated region (e.g., I/O
+ * devices often have a 32-bit limitation even in 64-bit systems). If zero
+ * then the user has no addressing restriction. This field is not used by
+ * XENMEM_decrease_reservation.
+ */
+#define XENMEMF_address_bits(x) (x)
+#define XENMEMF_get_address_bits(x) ((x) & 0xffu)
+/* NUMA node to allocate from. */
+#define XENMEMF_node(x) (((x) + 1) << 8)
+#define XENMEMF_get_node(x) ((((x) >> 8) - 1) & 0xffu)
+/* Flag to populate physmap with populate-on-demand entries */
+#define XENMEMF_populate_on_demand (1<<16)
+/* Flag to request allocation only from the node specified */
+#define XENMEMF_exact_node_request (1<<17)
+#define XENMEMF_exact_node(n) (XENMEMF_node(n) | XENMEMF_exact_node_request)
+#endif
+
+struct xen_memory_reservation {
+
+ /*
+ * XENMEM_increase_reservation:
+ * OUT: MFN (*not* GMFN) bases of extents that were allocated
+ * XENMEM_decrease_reservation:
+ * IN: GMFN bases of extents to free
+ * XENMEM_populate_physmap:
+ * IN: GPFN bases of extents to populate with memory
+ * OUT: GMFN bases of extents that were allocated
+ * (NB. This command also updates the mach_to_phys translation table)
+ * XENMEM_claim_pages:
+ * IN: must be zero
+ */
+ XEN_GUEST_HANDLE(xen_pfn_t) extent_start;
+
+ /* Number of extents, and size/alignment of each (2^extent_order pages). */
+ xen_ulong_t nr_extents;
+ unsigned int extent_order;
+
+#if __XEN_INTERFACE_VERSION__ >= 0x00030209
+ /* XENMEMF flags. */
+ unsigned int mem_flags;
+#else
+ unsigned int address_bits;
+#endif
+
+ /*
+ * Domain whose reservation is being changed.
+ * Unprivileged domains can specify only DOMID_SELF.
+ */
+ domid_t domid;
+};
+typedef struct xen_memory_reservation xen_memory_reservation_t;
+DEFINE_XEN_GUEST_HANDLE(xen_memory_reservation_t);
+
+/*
+ * An atomic exchange of memory pages. If return code is zero then
+ * @out.extent_list provides GMFNs of the newly-allocated memory.
+ * Returns zero on complete success, otherwise a negative error code.
+ * On complete success then always @nr_exchanged == @in.nr_extents.
+ * On partial success @nr_exchanged indicates how much work was done.
+ */
+#define XENMEM_exchange 11
+struct xen_memory_exchange {
+ /*
+ * [IN] Details of memory extents to be exchanged (GMFN bases).
+ * Note that @in.address_bits is ignored and unused.
+ */
+ struct xen_memory_reservation in;
+
+ /*
+ * [IN/OUT] Details of new memory extents.
+ * We require that:
+ * 1. @in.domid == @out.domid
+ * 2. @in.nr_extents << @in.extent_order ==
+ * @out.nr_extents << @out.extent_order
+ * 3. @in.extent_start and @out.extent_start lists must not overlap
+ * 4. @out.extent_start lists GPFN bases to be populated
+ * 5. @out.extent_start is overwritten with allocated GMFN bases
+ */
+ struct xen_memory_reservation out;
+
+ /*
+ * [OUT] Number of input extents that were successfully exchanged:
+ * 1. The first @nr_exchanged input extents were successfully
+ * deallocated.
+ * 2. The corresponding first entries in the output extent list correctly
+ * indicate the GMFNs that were successfully exchanged.
+ * 3. All other input and output extents are untouched.
+ * 4. If not all input exents are exchanged then the return code of this
+ * command will be non-zero.
+ * 5. THIS FIELD MUST BE INITIALISED TO ZERO BY THE CALLER!
+ */
+ xen_ulong_t nr_exchanged;
+};
+typedef struct xen_memory_exchange xen_memory_exchange_t;
+DEFINE_XEN_GUEST_HANDLE(xen_memory_exchange_t);
+
+/*
+ * Returns the maximum machine frame number of mapped RAM in this system.
+ * This command always succeeds (it never returns an error code).
+ * arg == NULL.
+ */
+#define XENMEM_maximum_ram_page 2
+
+/*
+ * Returns the current or maximum memory reservation, in pages, of the
+ * specified domain (may be DOMID_SELF). Returns -ve errcode on failure.
+ * arg == addr of domid_t.
+ */
+#define XENMEM_current_reservation 3
+#define XENMEM_maximum_reservation 4
+
+/*
+ * Returns the maximum GPFN in use by the guest, or -ve errcode on failure.
+ */
+#define XENMEM_maximum_gpfn 14
+
+/*
+ * Returns a list of MFN bases of 2MB extents comprising the machine_to_phys
+ * mapping table. Architectures which do not have a m2p table do not implement
+ * this command.
+ * arg == addr of xen_machphys_mfn_list_t.
+ */
+#define XENMEM_machphys_mfn_list 5
+struct xen_machphys_mfn_list {
+ /*
+ * Size of the 'extent_start' array. Fewer entries will be filled if the
+ * machphys table is smaller than max_extents * 2MB.
+ */
+ unsigned int max_extents;
+
+ /*
+ * Pointer to buffer to fill with list of extent starts. If there are
+ * any large discontiguities in the machine address space, 2MB gaps in
+ * the machphys table will be represented by an MFN base of zero.
+ */
+ XEN_GUEST_HANDLE(xen_pfn_t) extent_start;
+
+ /*
+ * Number of extents written to the above array. This will be smaller
+ * than 'max_extents' if the machphys table is smaller than max_e * 2MB.
+ */
+ unsigned int nr_extents;
+};
+typedef struct xen_machphys_mfn_list xen_machphys_mfn_list_t;
+DEFINE_XEN_GUEST_HANDLE(xen_machphys_mfn_list_t);
+
+/*
+ * For a compat caller, this is identical to XENMEM_machphys_mfn_list.
+ *
+ * For a non compat caller, this functions similarly to
+ * XENMEM_machphys_mfn_list, but returns the mfns making up the compatibility
+ * m2p table.
+ */
+#define XENMEM_machphys_compat_mfn_list 25
+
+/*
+ * Returns the location in virtual address space of the machine_to_phys
+ * mapping table. Architectures which do not have a m2p table, or which do not
+ * map it by default into guest address space, do not implement this command.
+ * arg == addr of xen_machphys_mapping_t.
+ */
+#define XENMEM_machphys_mapping 12
+struct xen_machphys_mapping {
+ xen_ulong_t v_start, v_end; /* Start and end virtual addresses. */
+ xen_ulong_t max_mfn; /* Maximum MFN that can be looked up. */
+};
+typedef struct xen_machphys_mapping xen_machphys_mapping_t;
+DEFINE_XEN_GUEST_HANDLE(xen_machphys_mapping_t);
+
+/* Source mapping space. */
+/* ` enum phys_map_space { */
+#define XENMAPSPACE_shared_info 0 /* shared info page */
+#define XENMAPSPACE_grant_table 1 /* grant table page */
+#define XENMAPSPACE_gmfn 2 /* GMFN */
+#define XENMAPSPACE_gmfn_range 3 /* GMFN range, XENMEM_add_to_physmap only. */
+#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another dom,
+ * XENMEM_add_to_physmap_batch only. */
+/* ` } */
+
+/*
+ * Sets the GPFN at which a particular page appears in the specified guest's
+ * pseudophysical address space.
+ * arg == addr of xen_add_to_physmap_t.
+ */
+#define XENMEM_add_to_physmap 7
+struct xen_add_to_physmap {
+ /* Which domain to change the mapping for. */
+ domid_t domid;
+
+ /* Number of pages to go through for gmfn_range */
+ uint16_t size;
+
+ unsigned int space; /* => enum phys_map_space */
+
+#define XENMAPIDX_grant_table_status 0x80000000
+
+ /* Index into space being mapped. */
+ xen_ulong_t idx;
+
+ /* GPFN in domid where the source mapping page should appear. */
+ xen_pfn_t gpfn;
+};
+typedef struct xen_add_to_physmap xen_add_to_physmap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
+
+/* A batched version of add_to_physmap. */
+#define XENMEM_add_to_physmap_batch 23
+struct xen_add_to_physmap_batch {
+ /* IN */
+ /* Which domain to change the mapping for. */
+ domid_t domid;
+ uint16_t space; /* => enum phys_map_space */
+
+ /* Number of pages to go through */
+ uint16_t size;
+ domid_t foreign_domid; /* IFF gmfn_foreign */
+
+ /* Indexes into space being mapped. */
+ XEN_GUEST_HANDLE(xen_ulong_t) idxs;
+
+ /* GPFN in domid where the source mapping page should appear. */
+ XEN_GUEST_HANDLE(xen_pfn_t) gpfns;
+
+ /* OUT */
+
+ /* Per index error code. */
+ XEN_GUEST_HANDLE(int) errs;
+};
+typedef struct xen_add_to_physmap_batch xen_add_to_physmap_batch_t;
+DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_batch_t);
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040400
+#define XENMEM_add_to_physmap_range XENMEM_add_to_physmap_batch
+#define xen_add_to_physmap_range xen_add_to_physmap_batch
+typedef struct xen_add_to_physmap_batch xen_add_to_physmap_range_t;
+DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_range_t);
+#endif
+
+/*
+ * Unmaps the page appearing at a particular GPFN from the specified guest's
+ * pseudophysical address space.
+ * arg == addr of xen_remove_from_physmap_t.
+ */
+#define XENMEM_remove_from_physmap 15
+struct xen_remove_from_physmap {
+ /* Which domain to change the mapping for. */
+ domid_t domid;
+
+ /* GPFN of the current mapping of the page. */
+ xen_pfn_t gpfn;
+};
+typedef struct xen_remove_from_physmap xen_remove_from_physmap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_remove_from_physmap_t);
+
+/*** REMOVED ***/
+/*#define XENMEM_translate_gpfn_list 8*/
+
+/*
+ * Returns the pseudo-physical memory map as it was when the domain
+ * was started (specified by XENMEM_set_memory_map).
+ * arg == addr of xen_memory_map_t.
+ */
+#define XENMEM_memory_map 9
+struct xen_memory_map {
+ /*
+ * On call the number of entries which can be stored in buffer. On
+ * return the number of entries which have been stored in
+ * buffer.
+ */
+ unsigned int nr_entries;
+
+ /*
+ * Entries in the buffer are in the same format as returned by the
+ * BIOS INT 0x15 EAX=0xE820 call.
+ */
+ XEN_GUEST_HANDLE(void) buffer;
+};
+typedef struct xen_memory_map xen_memory_map_t;
+DEFINE_XEN_GUEST_HANDLE(xen_memory_map_t);
+
+/*
+ * Returns the real physical memory map. Passes the same structure as
+ * XENMEM_memory_map.
+ * arg == addr of xen_memory_map_t.
+ */
+#define XENMEM_machine_memory_map 10
+
+/*
+ * Set the pseudo-physical memory map of a domain, as returned by
+ * XENMEM_memory_map.
+ * arg == addr of xen_foreign_memory_map_t.
+ */
+#define XENMEM_set_memory_map 13
+struct xen_foreign_memory_map {
+ domid_t domid;
+ struct xen_memory_map map;
+};
+typedef struct xen_foreign_memory_map xen_foreign_memory_map_t;
+DEFINE_XEN_GUEST_HANDLE(xen_foreign_memory_map_t);
+
+#define XENMEM_set_pod_target 16
+#define XENMEM_get_pod_target 17
+struct xen_pod_target {
+ /* IN */
+ uint64_t target_pages;
+ /* OUT */
+ uint64_t tot_pages;
+ uint64_t pod_cache_pages;
+ uint64_t pod_entries;
+ /* IN */
+ domid_t domid;
+};
+typedef struct xen_pod_target xen_pod_target_t;
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+#ifndef uint64_aligned_t
+#define uint64_aligned_t uint64_t
+#endif
+
+/*
+ * Get the number of MFNs saved through memory sharing.
+ * The call never fails.
+ */
+#define XENMEM_get_sharing_freed_pages 18
+#define XENMEM_get_sharing_shared_pages 19
+
+#define XENMEM_paging_op 20
+#define XENMEM_paging_op_nominate 0
+#define XENMEM_paging_op_evict 1
+#define XENMEM_paging_op_prep 2
+
+struct xen_mem_event_op {
+ uint8_t op; /* XENMEM_*_op_* */
+ domid_t domain;
+
+
+ /* PAGING_PREP IN: buffer to immediately fill page in */
+ uint64_aligned_t buffer;
+ /* Other OPs */
+ uint64_aligned_t gfn; /* IN: gfn of page being operated on */
+};
+typedef struct xen_mem_event_op xen_mem_event_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mem_event_op_t);
+
+#define XENMEM_access_op 21
+#define XENMEM_access_op_resume 0
+#define XENMEM_access_op_set_access 1
+#define XENMEM_access_op_get_access 2
+
+typedef enum {
+ XENMEM_access_n,
+ XENMEM_access_r,
+ XENMEM_access_w,
+ XENMEM_access_rw,
+ XENMEM_access_x,
+ XENMEM_access_rx,
+ XENMEM_access_wx,
+ XENMEM_access_rwx,
+ /*
+ * Page starts off as r-x, but automatically
+ * change to r-w on a write
+ */
+ XENMEM_access_rx2rw,
+ /*
+ * Log access: starts off as n, automatically
+ * goes to rwx, generating an event without
+ * pausing the vcpu
+ */
+ XENMEM_access_n2rwx,
+ /* Take the domain default */
+ XENMEM_access_default
+} xenmem_access_t;
+
+struct xen_mem_access_op {
+ /* XENMEM_access_op_* */
+ uint8_t op;
+ /* xenmem_access_t */
+ uint8_t access;
+ domid_t domid;
+ /*
+ * Number of pages for set op
+ * Ignored on setting default access and other ops
+ */
+ uint32_t nr;
+ /*
+ * First pfn for set op
+ * pfn for get op
+ * ~0ull is used to set and get the default access for pages
+ */
+ uint64_aligned_t pfn;
+};
+typedef struct xen_mem_access_op xen_mem_access_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mem_access_op_t);
+
+#define XENMEM_sharing_op 22
+#define XENMEM_sharing_op_nominate_gfn 0
+#define XENMEM_sharing_op_nominate_gref 1
+#define XENMEM_sharing_op_share 2
+#define XENMEM_sharing_op_resume 3
+#define XENMEM_sharing_op_debug_gfn 4
+#define XENMEM_sharing_op_debug_mfn 5
+#define XENMEM_sharing_op_debug_gref 6
+#define XENMEM_sharing_op_add_physmap 7
+#define XENMEM_sharing_op_audit 8
+
+#define XENMEM_SHARING_OP_S_HANDLE_INVALID (-10)
+#define XENMEM_SHARING_OP_C_HANDLE_INVALID (-9)
+
+/* The following allows sharing of grant refs. This is useful
+ * for sharing utilities sitting as "filters" in IO backends
+ * (e.g. memshr + blktap(2)). The IO backend is only exposed
+ * to grant references, and this allows sharing of the grefs */
+#define XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG (1ULL << 62)
+
+#define XENMEM_SHARING_OP_FIELD_MAKE_GREF(field, val) \
+ (field) = (XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG | val)
+#define XENMEM_SHARING_OP_FIELD_IS_GREF(field) \
+ ((field) & XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG)
+#define XENMEM_SHARING_OP_FIELD_GET_GREF(field) \
+ ((field) & (~XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG))
+
+struct xen_mem_sharing_op {
+ uint8_t op; /* XENMEM_sharing_op_* */
+ domid_t domain;
+
+ union {
+ struct mem_sharing_op_nominate { /* OP_NOMINATE_xxx */
+ union {
+ uint64_aligned_t gfn; /* IN: gfn to nominate */
+ uint32_t grant_ref; /* IN: grant ref to nominate */
+ } u;
+ uint64_aligned_t handle; /* OUT: the handle */
+ } nominate;
+ struct mem_sharing_op_share { /* OP_SHARE/ADD_PHYSMAP */
+ uint64_aligned_t source_gfn; /* IN: the gfn of the source page */
+ uint64_aligned_t source_handle; /* IN: handle to the source page */
+ uint64_aligned_t client_gfn; /* IN: the client gfn */
+ uint64_aligned_t client_handle; /* IN: handle to the client page */
+ domid_t client_domain; /* IN: the client domain id */
+ } share;
+ struct mem_sharing_op_debug { /* OP_DEBUG_xxx */
+ union {
+ uint64_aligned_t gfn; /* IN: gfn to debug */
+ uint64_aligned_t mfn; /* IN: mfn to debug */
+ uint32_t gref; /* IN: gref to debug */
+ } u;
+ } debug;
+ } u;
+};
+typedef struct xen_mem_sharing_op xen_mem_sharing_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mem_sharing_op_t);
+
+/*
+ * Attempt to stake a claim for a domain on a quantity of pages
+ * of system RAM, but _not_ assign specific pageframes. Only
+ * arithmetic is performed so the hypercall is very fast and need
+ * not be preemptible, thus sidestepping time-of-check-time-of-use
+ * races for memory allocation. Returns 0 if the hypervisor page
+ * allocator has atomically and successfully claimed the requested
+ * number of pages, else non-zero.
+ *
+ * Any domain may have only one active claim. When sufficient memory
+ * has been allocated to resolve the claim, the claim silently expires.
+ * Claiming zero pages effectively resets any outstanding claim and
+ * is always successful.
+ *
+ * Note that a valid claim may be staked even after memory has been
+ * allocated for a domain. In this case, the claim is not incremental,
+ * i.e. if the domain's tot_pages is 3, and a claim is staked for 10,
+ * only 7 additional pages are claimed.
+ *
+ * Caller must be privileged or the hypercall fails.
+ */
+#define XENMEM_claim_pages 24
+
+/*
+ * XENMEM_claim_pages flags - the are no flags at this time.
+ * The zero value is appropiate.
+ */
+
+#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+
+/*
+ * XENMEM_get_vnumainfo used by guest to get
+ * vNUMA topology from hypervisor.
+ */
+#define XENMEM_get_vnumainfo 26
+
+/* vNUMA node memory ranges */
+struct xen_vmemrange {
+ uint64_t start, end;
+ unsigned int flags;
+ unsigned int nid;
+};
+typedef struct xen_vmemrange xen_vmemrange_t;
+DEFINE_XEN_GUEST_HANDLE(xen_vmemrange_t);
+
+/*
+ * vNUMA topology specifies vNUMA node number, distance table,
+ * memory ranges and vcpu mapping provided for guests.
+ * XENMEM_get_vnumainfo hypercall expects to see from guest
+ * nr_vnodes, nr_vmemranges and nr_vcpus to indicate available memory.
+ * After filling guests structures, nr_vnodes, nr_vmemranges and nr_vcpus
+ * copied back to guest. Domain returns expected values of nr_vnodes,
+ * nr_vmemranges and nr_vcpus to guest if the values where incorrect.
+ */
+struct xen_vnuma_topology_info {
+ /* IN */
+ domid_t domid;
+ uint16_t pad;
+ /* IN/OUT */
+ unsigned int nr_vnodes;
+ unsigned int nr_vcpus;
+ unsigned int nr_vmemranges;
+ /* OUT */
+ union {
+ XEN_GUEST_HANDLE(uint) h;
+ uint64_t pad;
+ } vdistance;
+ union {
+ XEN_GUEST_HANDLE(uint) h;
+ uint64_t pad;
+ } vcpu_to_vnode;
+ union {
+ XEN_GUEST_HANDLE(xen_vmemrange_t) h;
+ uint64_t pad;
+ } vmemrange;
+};
+typedef struct xen_vnuma_topology_info xen_vnuma_topology_info_t;
+DEFINE_XEN_GUEST_HANDLE(xen_vnuma_topology_info_t);
+
+/* Next available subop number is 27 */
+
+#endif /* __XEN_PUBLIC_MEMORY_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * nmi.h
+ *
+ * NMI callback registration and reason codes.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
+ */
+
+#ifndef __XEN_PUBLIC_NMI_H__
+#define __XEN_PUBLIC_NMI_H__
+
+#include "xen.h"
+
+/*
+ * NMI reason codes:
+ * Currently these are x86-specific, stored in arch_shared_info.nmi_reason.
+ */
+ /* I/O-check error reported via ISA port 0x61, bit 6. */
+#define _XEN_NMIREASON_io_error 0
+#define XEN_NMIREASON_io_error (1UL << _XEN_NMIREASON_io_error)
+ /* PCI SERR reported via ISA port 0x61, bit 7. */
+#define _XEN_NMIREASON_pci_serr 1
+#define XEN_NMIREASON_pci_serr (1UL << _XEN_NMIREASON_pci_serr)
+#if __XEN_INTERFACE_VERSION__ < 0x00040300 /* legacy alias of the above */
+ /* Parity error reported via ISA port 0x61, bit 7. */
+#define _XEN_NMIREASON_parity_error 1
+#define XEN_NMIREASON_parity_error (1UL << _XEN_NMIREASON_parity_error)
+#endif
+ /* Unknown hardware-generated NMI. */
+#define _XEN_NMIREASON_unknown 2
+#define XEN_NMIREASON_unknown (1UL << _XEN_NMIREASON_unknown)
+
+/*
+ * long nmi_op(unsigned int cmd, void *arg)
+ * NB. All ops return zero on success, else a negative error code.
+ */
+
+/*
+ * Register NMI callback for this (calling) VCPU. Currently this only makes
+ * sense for domain 0, vcpu 0. All other callers will be returned EINVAL.
+ * arg == pointer to xennmi_callback structure.
+ */
+#define XENNMI_register_callback 0
+struct xennmi_callback {
+ unsigned long handler_address;
+ unsigned long pad;
+};
+typedef struct xennmi_callback xennmi_callback_t;
+DEFINE_XEN_GUEST_HANDLE(xennmi_callback_t);
+
+/*
+ * Deregister NMI callback for this (calling) VCPU.
+ * arg == NULL.
+ */
+#define XENNMI_unregister_callback 1
+
+#endif /* __XEN_PUBLIC_NMI_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PUBLIC_PHYSDEV_H__
+#define __XEN_PUBLIC_PHYSDEV_H__
+
+#include "xen.h"
+
+/*
+ * Prototype for this hypercall is:
+ * int physdev_op(int cmd, void *args)
+ * @cmd == PHYSDEVOP_??? (physdev operation).
+ * @args == Operation-specific extra arguments (NULL if none).
+ */
+
+/*
+ * Notify end-of-interrupt (EOI) for the specified IRQ.
+ * @arg == pointer to physdev_eoi structure.
+ */
+#define PHYSDEVOP_eoi 12
+struct physdev_eoi {
+ /* IN */
+ uint32_t irq;
+};
+typedef struct physdev_eoi physdev_eoi_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_eoi_t);
+
+/*
+ * Register a shared page for the hypervisor to indicate whether the guest
+ * must issue PHYSDEVOP_eoi. The semantics of PHYSDEVOP_eoi change slightly
+ * once the guest used this function in that the associated event channel
+ * will automatically get unmasked. The page registered is used as a bit
+ * array indexed by Xen's PIRQ value.
+ */
+#define PHYSDEVOP_pirq_eoi_gmfn_v1 17
+/*
+ * Register a shared page for the hypervisor to indicate whether the
+ * guest must issue PHYSDEVOP_eoi. This hypercall is very similar to
+ * PHYSDEVOP_pirq_eoi_gmfn_v1 but it doesn't change the semantics of
+ * PHYSDEVOP_eoi. The page registered is used as a bit array indexed by
+ * Xen's PIRQ value.
+ */
+#define PHYSDEVOP_pirq_eoi_gmfn_v2 28
+struct physdev_pirq_eoi_gmfn {
+ /* IN */
+ xen_pfn_t gmfn;
+};
+typedef struct physdev_pirq_eoi_gmfn physdev_pirq_eoi_gmfn_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_pirq_eoi_gmfn_t);
+
+/*
+ * Query the status of an IRQ line.
+ * @arg == pointer to physdev_irq_status_query structure.
+ */
+#define PHYSDEVOP_irq_status_query 5
+struct physdev_irq_status_query {
+ /* IN */
+ uint32_t irq;
+ /* OUT */
+ uint32_t flags; /* XENIRQSTAT_* */
+};
+typedef struct physdev_irq_status_query physdev_irq_status_query_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_irq_status_query_t);
+
+/* Need to call PHYSDEVOP_eoi when the IRQ has been serviced? */
+#define _XENIRQSTAT_needs_eoi (0)
+#define XENIRQSTAT_needs_eoi (1U<<_XENIRQSTAT_needs_eoi)
+
+/* IRQ shared by multiple guests? */
+#define _XENIRQSTAT_shared (1)
+#define XENIRQSTAT_shared (1U<<_XENIRQSTAT_shared)
+
+/*
+ * Set the current VCPU's I/O privilege level.
+ * @arg == pointer to physdev_set_iopl structure.
+ */
+#define PHYSDEVOP_set_iopl 6
+struct physdev_set_iopl {
+ /* IN */
+ uint32_t iopl;
+};
+typedef struct physdev_set_iopl physdev_set_iopl_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_set_iopl_t);
+
+/*
+ * Set the current VCPU's I/O-port permissions bitmap.
+ * @arg == pointer to physdev_set_iobitmap structure.
+ */
+#define PHYSDEVOP_set_iobitmap 7
+struct physdev_set_iobitmap {
+ /* IN */
+#if __XEN_INTERFACE_VERSION__ >= 0x00030205
+ XEN_GUEST_HANDLE(uint8) bitmap;
+#else
+ uint8_t *bitmap;
+#endif
+ uint32_t nr_ports;
+};
+typedef struct physdev_set_iobitmap physdev_set_iobitmap_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_set_iobitmap_t);
+
+/*
+ * Read or write an IO-APIC register.
+ * @arg == pointer to physdev_apic structure.
+ */
+#define PHYSDEVOP_apic_read 8
+#define PHYSDEVOP_apic_write 9
+struct physdev_apic {
+ /* IN */
+ unsigned long apic_physbase;
+ uint32_t reg;
+ /* IN or OUT */
+ uint32_t value;
+};
+typedef struct physdev_apic physdev_apic_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_apic_t);
+
+/*
+ * Allocate or free a physical upcall vector for the specified IRQ line.
+ * @arg == pointer to physdev_irq structure.
+ */
+#define PHYSDEVOP_alloc_irq_vector 10
+#define PHYSDEVOP_free_irq_vector 11
+struct physdev_irq {
+ /* IN */
+ uint32_t irq;
+ /* IN or OUT */
+ uint32_t vector;
+};
+typedef struct physdev_irq physdev_irq_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_irq_t);
+
+#define MAP_PIRQ_TYPE_MSI 0x0
+#define MAP_PIRQ_TYPE_GSI 0x1
+#define MAP_PIRQ_TYPE_UNKNOWN 0x2
+#define MAP_PIRQ_TYPE_MSI_SEG 0x3
+#define MAP_PIRQ_TYPE_MULTI_MSI 0x4
+
+#define PHYSDEVOP_map_pirq 13
+struct physdev_map_pirq {
+ domid_t domid;
+ /* IN */
+ int type;
+ /* IN (ignored for ..._MULTI_MSI) */
+ int index;
+ /* IN or OUT */
+ int pirq;
+ /* IN - high 16 bits hold segment for ..._MSI_SEG and ..._MULTI_MSI */
+ int bus;
+ /* IN */
+ int devfn;
+ /* IN (also OUT for ..._MULTI_MSI) */
+ int entry_nr;
+ /* IN */
+ uint64_t table_base;
+};
+typedef struct physdev_map_pirq physdev_map_pirq_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_map_pirq_t);
+
+#define PHYSDEVOP_unmap_pirq 14
+struct physdev_unmap_pirq {
+ domid_t domid;
+ /* IN */
+ int pirq;
+};
+
+typedef struct physdev_unmap_pirq physdev_unmap_pirq_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_unmap_pirq_t);
+
+#define PHYSDEVOP_manage_pci_add 15
+#define PHYSDEVOP_manage_pci_remove 16
+struct physdev_manage_pci {
+ /* IN */
+ uint8_t bus;
+ uint8_t devfn;
+};
+
+typedef struct physdev_manage_pci physdev_manage_pci_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_t);
+
+#define PHYSDEVOP_restore_msi 19
+struct physdev_restore_msi {
+ /* IN */
+ uint8_t bus;
+ uint8_t devfn;
+};
+typedef struct physdev_restore_msi physdev_restore_msi_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_restore_msi_t);
+
+#define PHYSDEVOP_manage_pci_add_ext 20
+struct physdev_manage_pci_ext {
+ /* IN */
+ uint8_t bus;
+ uint8_t devfn;
+ unsigned is_extfn;
+ unsigned is_virtfn;
+ struct {
+ uint8_t bus;
+ uint8_t devfn;
+ } physfn;
+};
+
+typedef struct physdev_manage_pci_ext physdev_manage_pci_ext_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_ext_t);
+
+/*
+ * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op()
+ * hypercall since 0x00030202.
+ */
+struct physdev_op {
+ uint32_t cmd;
+ union {
+ struct physdev_irq_status_query irq_status_query;
+ struct physdev_set_iopl set_iopl;
+ struct physdev_set_iobitmap set_iobitmap;
+ struct physdev_apic apic_op;
+ struct physdev_irq irq_op;
+ } u;
+};
+typedef struct physdev_op physdev_op_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_op_t);
+
+#define PHYSDEVOP_setup_gsi 21
+struct physdev_setup_gsi {
+ int gsi;
+ /* IN */
+ uint8_t triggering;
+ /* IN */
+ uint8_t polarity;
+ /* IN */
+};
+
+typedef struct physdev_setup_gsi physdev_setup_gsi_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_setup_gsi_t);
+
+/* leave PHYSDEVOP 22 free */
+
+/* type is MAP_PIRQ_TYPE_GSI or MAP_PIRQ_TYPE_MSI
+ * the hypercall returns a free pirq */
+#define PHYSDEVOP_get_free_pirq 23
+struct physdev_get_free_pirq {
+ /* IN */
+ int type;
+ /* OUT */
+ uint32_t pirq;
+};
+
+typedef struct physdev_get_free_pirq physdev_get_free_pirq_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_get_free_pirq_t);
+
+#define XEN_PCI_MMCFG_RESERVED 0x1
+
+#define PHYSDEVOP_pci_mmcfg_reserved 24
+struct physdev_pci_mmcfg_reserved {
+ uint64_t address;
+ uint16_t segment;
+ uint8_t start_bus;
+ uint8_t end_bus;
+ uint32_t flags;
+};
+typedef struct physdev_pci_mmcfg_reserved physdev_pci_mmcfg_reserved_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_pci_mmcfg_reserved_t);
+
+#define XEN_PCI_DEV_EXTFN 0x1
+#define XEN_PCI_DEV_VIRTFN 0x2
+#define XEN_PCI_DEV_PXM 0x4
+
+#define PHYSDEVOP_pci_device_add 25
+struct physdev_pci_device_add {
+ /* IN */
+ uint16_t seg;
+ uint8_t bus;
+ uint8_t devfn;
+ uint32_t flags;
+ struct {
+ uint8_t bus;
+ uint8_t devfn;
+ } physfn;
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+ uint32_t optarr[];
+#elif defined(__GNUC__)
+ uint32_t optarr[0];
+#endif
+};
+typedef struct physdev_pci_device_add physdev_pci_device_add_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_pci_device_add_t);
+
+#define PHYSDEVOP_pci_device_remove 26
+#define PHYSDEVOP_restore_msi_ext 27
+/*
+ * Dom0 should use these two to announce MMIO resources assigned to
+ * MSI-X capable devices won't (prepare) or may (release) change.
+ */
+#define PHYSDEVOP_prepare_msix 30
+#define PHYSDEVOP_release_msix 31
+struct physdev_pci_device {
+ /* IN */
+ uint16_t seg;
+ uint8_t bus;
+ uint8_t devfn;
+};
+typedef struct physdev_pci_device physdev_pci_device_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_pci_device_t);
+
+#define PHYSDEVOP_DBGP_RESET_PREPARE 1
+#define PHYSDEVOP_DBGP_RESET_DONE 2
+
+#define PHYSDEVOP_DBGP_BUS_UNKNOWN 0
+#define PHYSDEVOP_DBGP_BUS_PCI 1
+
+#define PHYSDEVOP_dbgp_op 29
+struct physdev_dbgp_op {
+ /* IN */
+ uint8_t op;
+ uint8_t bus;
+ union {
+ struct physdev_pci_device pci;
+ } u;
+};
+typedef struct physdev_dbgp_op physdev_dbgp_op_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_dbgp_op_t);
+
+/*
+ * Notify that some PIRQ-bound event channels have been unmasked.
+ * ** This command is obsolete since interface version 0x00030202 and is **
+ * ** unsupported by newer versions of Xen. **
+ */
+#define PHYSDEVOP_IRQ_UNMASK_NOTIFY 4
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040600
+/*
+ * These all-capitals physdev operation names are superceded by the new names
+ * (defined above) since interface version 0x00030202. The guard above was
+ * added post-4.5 only though and hence shouldn't check for 0x00030202.
+ */
+#define PHYSDEVOP_IRQ_STATUS_QUERY PHYSDEVOP_irq_status_query
+#define PHYSDEVOP_SET_IOPL PHYSDEVOP_set_iopl
+#define PHYSDEVOP_SET_IOBITMAP PHYSDEVOP_set_iobitmap
+#define PHYSDEVOP_APIC_READ PHYSDEVOP_apic_read
+#define PHYSDEVOP_APIC_WRITE PHYSDEVOP_apic_write
+#define PHYSDEVOP_ASSIGN_VECTOR PHYSDEVOP_alloc_irq_vector
+#define PHYSDEVOP_FREE_VECTOR PHYSDEVOP_free_irq_vector
+#define PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY XENIRQSTAT_needs_eoi
+#define PHYSDEVOP_IRQ_SHARED XENIRQSTAT_shared
+#endif
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040200
+#define PHYSDEVOP_pirq_eoi_gmfn PHYSDEVOP_pirq_eoi_gmfn_v1
+#else
+#define PHYSDEVOP_pirq_eoi_gmfn PHYSDEVOP_pirq_eoi_gmfn_v2
+#endif
+
+#endif /* __XEN_PUBLIC_PHYSDEV_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * platform.h
+ *
+ * Hardware platform operations. Intended for use by domain-0 kernel.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2002-2006, K Fraser
+ */
+
+#ifndef __XEN_PUBLIC_PLATFORM_H__
+#define __XEN_PUBLIC_PLATFORM_H__
+
+#include "xen.h"
+
+#define XENPF_INTERFACE_VERSION 0x03000001
+
+/*
+ * Set clock such that it would read <secs,nsecs> after 00:00:00 UTC,
+ * 1 January, 1970 if the current system time was <system_time>.
+ */
+#define XENPF_settime 17
+struct xenpf_settime {
+ /* IN variables. */
+ uint32_t secs;
+ uint32_t nsecs;
+ uint64_t system_time;
+};
+typedef struct xenpf_settime xenpf_settime_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_settime_t);
+
+/*
+ * Request memory range (@mfn, @mfn+@nr_mfns-1) to have type @type.
+ * On x86, @type is an architecture-defined MTRR memory type.
+ * On success, returns the MTRR that was used (@reg) and a handle that can
+ * be passed to XENPF_DEL_MEMTYPE to accurately tear down the new setting.
+ * (x86-specific).
+ */
+#define XENPF_add_memtype 31
+struct xenpf_add_memtype {
+ /* IN variables. */
+ xen_pfn_t mfn;
+ uint64_t nr_mfns;
+ uint32_t type;
+ /* OUT variables. */
+ uint32_t handle;
+ uint32_t reg;
+};
+typedef struct xenpf_add_memtype xenpf_add_memtype_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_add_memtype_t);
+
+/*
+ * Tear down an existing memory-range type. If @handle is remembered then it
+ * should be passed in to accurately tear down the correct setting (in case
+ * of overlapping memory regions with differing types). If it is not known
+ * then @handle should be set to zero. In all cases @reg must be set.
+ * (x86-specific).
+ */
+#define XENPF_del_memtype 32
+struct xenpf_del_memtype {
+ /* IN variables. */
+ uint32_t handle;
+ uint32_t reg;
+};
+typedef struct xenpf_del_memtype xenpf_del_memtype_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_del_memtype_t);
+
+/* Read current type of an MTRR (x86-specific). */
+#define XENPF_read_memtype 33
+struct xenpf_read_memtype {
+ /* IN variables. */
+ uint32_t reg;
+ /* OUT variables. */
+ xen_pfn_t mfn;
+ uint64_t nr_mfns;
+ uint32_t type;
+};
+typedef struct xenpf_read_memtype xenpf_read_memtype_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_read_memtype_t);
+
+#define XENPF_microcode_update 35
+struct xenpf_microcode_update {
+ /* IN variables. */
+ XEN_GUEST_HANDLE(const_void) data;/* Pointer to microcode data */
+ uint32_t length; /* Length of microcode data. */
+};
+typedef struct xenpf_microcode_update xenpf_microcode_update_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_microcode_update_t);
+
+#define XENPF_platform_quirk 39
+#define QUIRK_NOIRQBALANCING 1 /* Do not restrict IO-APIC RTE targets */
+#define QUIRK_IOAPIC_BAD_REGSEL 2 /* IO-APIC REGSEL forgets its value */
+#define QUIRK_IOAPIC_GOOD_REGSEL 3 /* IO-APIC REGSEL behaves properly */
+struct xenpf_platform_quirk {
+ /* IN variables. */
+ uint32_t quirk_id;
+};
+typedef struct xenpf_platform_quirk xenpf_platform_quirk_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_platform_quirk_t);
+
+#define XENPF_efi_runtime_call 49
+#define XEN_EFI_get_time 1
+#define XEN_EFI_set_time 2
+#define XEN_EFI_get_wakeup_time 3
+#define XEN_EFI_set_wakeup_time 4
+#define XEN_EFI_get_next_high_monotonic_count 5
+#define XEN_EFI_get_variable 6
+#define XEN_EFI_set_variable 7
+#define XEN_EFI_get_next_variable_name 8
+#define XEN_EFI_query_variable_info 9
+#define XEN_EFI_query_capsule_capabilities 10
+#define XEN_EFI_update_capsule 11
+struct xenpf_efi_runtime_call {
+ uint32_t function;
+ /*
+ * This field is generally used for per sub-function flags (defined
+ * below), except for the XEN_EFI_get_next_high_monotonic_count case,
+ * where it holds the single returned value.
+ */
+ uint32_t misc;
+ xen_ulong_t status;
+ union {
+#define XEN_EFI_GET_TIME_SET_CLEARS_NS 0x00000001
+ struct {
+ struct xenpf_efi_time {
+ uint16_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t min;
+ uint8_t sec;
+ uint32_t ns;
+ int16_t tz;
+ uint8_t daylight;
+ } time;
+ uint32_t resolution;
+ uint32_t accuracy;
+ } get_time;
+
+ struct xenpf_efi_time set_time;
+
+#define XEN_EFI_GET_WAKEUP_TIME_ENABLED 0x00000001
+#define XEN_EFI_GET_WAKEUP_TIME_PENDING 0x00000002
+ struct xenpf_efi_time get_wakeup_time;
+
+#define XEN_EFI_SET_WAKEUP_TIME_ENABLE 0x00000001
+#define XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY 0x00000002
+ struct xenpf_efi_time set_wakeup_time;
+
+#define XEN_EFI_VARIABLE_NON_VOLATILE 0x00000001
+#define XEN_EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
+#define XEN_EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
+ struct {
+ XEN_GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
+ xen_ulong_t size;
+ XEN_GUEST_HANDLE(void) data;
+ struct xenpf_efi_guid {
+ uint32_t data1;
+ uint16_t data2;
+ uint16_t data3;
+ uint8_t data4[8];
+ } vendor_guid;
+ } get_variable, set_variable;
+
+ struct {
+ xen_ulong_t size;
+ XEN_GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
+ struct xenpf_efi_guid vendor_guid;
+ } get_next_variable_name;
+
+#define XEN_EFI_VARINFO_BOOT_SNAPSHOT 0x00000001
+ struct {
+ uint32_t attr;
+ uint64_t max_store_size;
+ uint64_t remain_store_size;
+ uint64_t max_size;
+ } query_variable_info;
+
+ struct {
+ XEN_GUEST_HANDLE(void) capsule_header_array;
+ xen_ulong_t capsule_count;
+ uint64_t max_capsule_size;
+ uint32_t reset_type;
+ } query_capsule_capabilities;
+
+ struct {
+ XEN_GUEST_HANDLE(void) capsule_header_array;
+ xen_ulong_t capsule_count;
+ uint64_t sg_list; /* machine address */
+ } update_capsule;
+ } u;
+};
+typedef struct xenpf_efi_runtime_call xenpf_efi_runtime_call_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_efi_runtime_call_t);
+
+#define XENPF_firmware_info 50
+#define XEN_FW_DISK_INFO 1 /* from int 13 AH=08/41/48 */
+#define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */
+#define XEN_FW_VBEDDC_INFO 3 /* from int 10 AX=4f15 */
+#define XEN_FW_EFI_INFO 4 /* from EFI */
+#define XEN_FW_EFI_VERSION 0
+#define XEN_FW_EFI_CONFIG_TABLE 1
+#define XEN_FW_EFI_VENDOR 2
+#define XEN_FW_EFI_MEM_INFO 3
+#define XEN_FW_EFI_RT_VERSION 4
+#define XEN_FW_EFI_PCI_ROM 5
+#define XEN_FW_KBD_SHIFT_FLAGS 5
+struct xenpf_firmware_info {
+ /* IN variables. */
+ uint32_t type;
+ uint32_t index;
+ /* OUT variables. */
+ union {
+ struct {
+ /* Int13, Fn48: Check Extensions Present. */
+ uint8_t device; /* %dl: bios device number */
+ uint8_t version; /* %ah: major version */
+ uint16_t interface_support; /* %cx: support bitmap */
+ /* Int13, Fn08: Legacy Get Device Parameters. */
+ uint16_t legacy_max_cylinder; /* %cl[7:6]:%ch: max cyl # */
+ uint8_t legacy_max_head; /* %dh: max head # */
+ uint8_t legacy_sectors_per_track; /* %cl[5:0]: max sector # */
+ /* Int13, Fn41: Get Device Parameters (as filled into %ds:%esi). */
+ /* NB. First uint16_t of buffer must be set to buffer size. */
+ XEN_GUEST_HANDLE(void) edd_params;
+ } disk_info; /* XEN_FW_DISK_INFO */
+ struct {
+ uint8_t device; /* bios device number */
+ uint32_t mbr_signature; /* offset 0x1b8 in mbr */
+ } disk_mbr_signature; /* XEN_FW_DISK_MBR_SIGNATURE */
+ struct {
+ /* Int10, AX=4F15: Get EDID info. */
+ uint8_t capabilities;
+ uint8_t edid_transfer_time;
+ /* must refer to 128-byte buffer */
+ XEN_GUEST_HANDLE(uint8) edid;
+ } vbeddc_info; /* XEN_FW_VBEDDC_INFO */
+ union xenpf_efi_info {
+ uint32_t version;
+ struct {
+ uint64_t addr; /* EFI_CONFIGURATION_TABLE */
+ uint32_t nent;
+ } cfg;
+ struct {
+ uint32_t revision;
+ uint32_t bufsz; /* input, in bytes */
+ XEN_GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
+ } vendor;
+ struct {
+ uint64_t addr;
+ uint64_t size;
+ uint64_t attr;
+ uint32_t type;
+ } mem;
+ struct {
+ /* IN variables */
+ uint16_t segment;
+ uint8_t bus;
+ uint8_t devfn;
+ uint16_t vendor;
+ uint16_t devid;
+ /* OUT variables */
+ uint64_t address;
+ xen_ulong_t size;
+ } pci_rom;
+ } efi_info; /* XEN_FW_EFI_INFO */
+
+ /* Int16, Fn02: Get keyboard shift flags. */
+ uint8_t kbd_shift_flags; /* XEN_FW_KBD_SHIFT_FLAGS */
+ } u;
+};
+typedef struct xenpf_firmware_info xenpf_firmware_info_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_firmware_info_t);
+
+#define XENPF_enter_acpi_sleep 51
+struct xenpf_enter_acpi_sleep {
+ /* IN variables */
+#if __XEN_INTERFACE_VERSION__ < 0x00040300
+ uint16_t pm1a_cnt_val; /* PM1a control value. */
+ uint16_t pm1b_cnt_val; /* PM1b control value. */
+#else
+ uint16_t val_a; /* PM1a control / sleep type A. */
+ uint16_t val_b; /* PM1b control / sleep type B. */
+#endif
+ uint32_t sleep_state; /* Which state to enter (Sn). */
+#define XENPF_ACPI_SLEEP_EXTENDED 0x00000001
+ uint32_t flags; /* XENPF_ACPI_SLEEP_*. */
+};
+typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t);
+
+#define XENPF_change_freq 52
+struct xenpf_change_freq {
+ /* IN variables */
+ uint32_t flags; /* Must be zero. */
+ uint32_t cpu; /* Physical cpu. */
+ uint64_t freq; /* New frequency (Hz). */
+};
+typedef struct xenpf_change_freq xenpf_change_freq_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_change_freq_t);
+
+/*
+ * Get idle times (nanoseconds since boot) for physical CPUs specified in the
+ * @cpumap_bitmap with range [0..@cpumap_nr_cpus-1]. The @idletime array is
+ * indexed by CPU number; only entries with the corresponding @cpumap_bitmap
+ * bit set are written to. On return, @cpumap_bitmap is modified so that any
+ * non-existent CPUs are cleared. Such CPUs have their @idletime array entry
+ * cleared.
+ */
+#define XENPF_getidletime 53
+struct xenpf_getidletime {
+ /* IN/OUT variables */
+ /* IN: CPUs to interrogate; OUT: subset of IN which are present */
+ XEN_GUEST_HANDLE(uint8) cpumap_bitmap;
+ /* IN variables */
+ /* Size of cpumap bitmap. */
+ uint32_t cpumap_nr_cpus;
+ /* Must be indexable for every cpu in cpumap_bitmap. */
+ XEN_GUEST_HANDLE(uint64) idletime;
+ /* OUT variables */
+ /* System time when the idletime snapshots were taken. */
+ uint64_t now;
+};
+typedef struct xenpf_getidletime xenpf_getidletime_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_getidletime_t);
+
+#define XENPF_set_processor_pminfo 54
+
+/* ability bits */
+#define XEN_PROCESSOR_PM_CX 1
+#define XEN_PROCESSOR_PM_PX 2
+#define XEN_PROCESSOR_PM_TX 4
+
+/* cmd type */
+#define XEN_PM_CX 0
+#define XEN_PM_PX 1
+#define XEN_PM_TX 2
+#define XEN_PM_PDC 3
+
+/* Px sub info type */
+#define XEN_PX_PCT 1
+#define XEN_PX_PSS 2
+#define XEN_PX_PPC 4
+#define XEN_PX_PSD 8
+
+struct xen_power_register {
+ uint32_t space_id;
+ uint32_t bit_width;
+ uint32_t bit_offset;
+ uint32_t access_size;
+ uint64_t address;
+};
+
+struct xen_processor_csd {
+ uint32_t domain; /* domain number of one dependent group */
+ uint32_t coord_type; /* coordination type */
+ uint32_t num; /* number of processors in same domain */
+};
+typedef struct xen_processor_csd xen_processor_csd_t;
+DEFINE_XEN_GUEST_HANDLE(xen_processor_csd_t);
+
+struct xen_processor_cx {
+ struct xen_power_register reg; /* GAS for Cx trigger register */
+ uint8_t type; /* cstate value, c0: 0, c1: 1, ... */
+ uint32_t latency; /* worst latency (ms) to enter/exit this cstate */
+ uint32_t power; /* average power consumption(mW) */
+ uint32_t dpcnt; /* number of dependency entries */
+ XEN_GUEST_HANDLE(xen_processor_csd_t) dp; /* NULL if no dependency */
+};
+typedef struct xen_processor_cx xen_processor_cx_t;
+DEFINE_XEN_GUEST_HANDLE(xen_processor_cx_t);
+
+struct xen_processor_flags {
+ uint32_t bm_control:1;
+ uint32_t bm_check:1;
+ uint32_t has_cst:1;
+ uint32_t power_setup_done:1;
+ uint32_t bm_rld_set:1;
+};
+
+struct xen_processor_power {
+ uint32_t count; /* number of C state entries in array below */
+ struct xen_processor_flags flags; /* global flags of this processor */
+ XEN_GUEST_HANDLE(xen_processor_cx_t) states; /* supported c states */
+};
+
+struct xen_pct_register {
+ uint8_t descriptor;
+ uint16_t length;
+ uint8_t space_id;
+ uint8_t bit_width;
+ uint8_t bit_offset;
+ uint8_t reserved;
+ uint64_t address;
+};
+
+struct xen_processor_px {
+ uint64_t core_frequency; /* megahertz */
+ uint64_t power; /* milliWatts */
+ uint64_t transition_latency; /* microseconds */
+ uint64_t bus_master_latency; /* microseconds */
+ uint64_t control; /* control value */
+ uint64_t status; /* success indicator */
+};
+typedef struct xen_processor_px xen_processor_px_t;
+DEFINE_XEN_GUEST_HANDLE(xen_processor_px_t);
+
+struct xen_psd_package {
+ uint64_t num_entries;
+ uint64_t revision;
+ uint64_t domain;
+ uint64_t coord_type;
+ uint64_t num_processors;
+};
+
+struct xen_processor_performance {
+ uint32_t flags; /* flag for Px sub info type */
+ uint32_t platform_limit; /* Platform limitation on freq usage */
+ struct xen_pct_register control_register;
+ struct xen_pct_register status_register;
+ uint32_t state_count; /* total available performance states */
+ XEN_GUEST_HANDLE(xen_processor_px_t) states;
+ struct xen_psd_package domain_info;
+ uint32_t shared_type; /* coordination type of this processor */
+};
+typedef struct xen_processor_performance xen_processor_performance_t;
+DEFINE_XEN_GUEST_HANDLE(xen_processor_performance_t);
+
+struct xenpf_set_processor_pminfo {
+ /* IN variables */
+ uint32_t id; /* ACPI CPU ID */
+ uint32_t type; /* {XEN_PM_CX, XEN_PM_PX} */
+ union {
+ struct xen_processor_power power;/* Cx: _CST/_CSD */
+ struct xen_processor_performance perf; /* Px: _PPC/_PCT/_PSS/_PSD */
+ XEN_GUEST_HANDLE(uint32) pdc; /* _PDC */
+ } u;
+};
+typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_set_processor_pminfo_t);
+
+#define XENPF_get_cpuinfo 55
+struct xenpf_pcpuinfo {
+ /* IN */
+ uint32_t xen_cpuid;
+ /* OUT */
+ /* The maxium cpu_id that is present */
+ uint32_t max_present;
+#define XEN_PCPU_FLAGS_ONLINE 1
+ /* Correponding xen_cpuid is not present*/
+#define XEN_PCPU_FLAGS_INVALID 2
+ uint32_t flags;
+ uint32_t apic_id;
+ uint32_t acpi_id;
+};
+typedef struct xenpf_pcpuinfo xenpf_pcpuinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_pcpuinfo_t);
+
+#define XENPF_get_cpu_version 48
+struct xenpf_pcpu_version {
+ /* IN */
+ uint32_t xen_cpuid;
+ /* OUT */
+ /* The maxium cpu_id that is present */
+ uint32_t max_present;
+ char vendor_id[12];
+ uint32_t family;
+ uint32_t model;
+ uint32_t stepping;
+};
+typedef struct xenpf_pcpu_version xenpf_pcpu_version_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_pcpu_version_t);
+
+#define XENPF_cpu_online 56
+#define XENPF_cpu_offline 57
+struct xenpf_cpu_ol
+{
+ uint32_t cpuid;
+};
+typedef struct xenpf_cpu_ol xenpf_cpu_ol_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_cpu_ol_t);
+
+#define XENPF_cpu_hotadd 58
+struct xenpf_cpu_hotadd
+{
+ uint32_t apic_id;
+ uint32_t acpi_id;
+ uint32_t pxm;
+};
+
+#define XENPF_mem_hotadd 59
+struct xenpf_mem_hotadd
+{
+ uint64_t spfn;
+ uint64_t epfn;
+ uint32_t pxm;
+ uint32_t flags;
+};
+
+#define XENPF_core_parking 60
+
+#define XEN_CORE_PARKING_SET 1
+#define XEN_CORE_PARKING_GET 2
+struct xenpf_core_parking {
+ /* IN variables */
+ uint32_t type;
+ /* IN variables: set cpu nums expected to be idled */
+ /* OUT variables: get cpu nums actually be idled */
+ uint32_t idle_nums;
+};
+typedef struct xenpf_core_parking xenpf_core_parking_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_core_parking_t);
+
+/*
+ * Access generic platform resources(e.g., accessing MSR, port I/O, etc)
+ * in unified way. Batch resource operations in one call are supported and
+ * they are always non-preemptible and executed in their original order.
+ * The batch itself returns a negative integer for general errors, or a
+ * non-negative integer for the number of successful operations. For the latter
+ * case, the @ret in the failed entry (if any) indicates the exact error.
+ */
+#define XENPF_resource_op 61
+
+#define XEN_RESOURCE_OP_MSR_READ 0
+#define XEN_RESOURCE_OP_MSR_WRITE 1
+
+struct xenpf_resource_entry {
+ union {
+ uint32_t cmd; /* IN: XEN_RESOURCE_OP_* */
+ int32_t ret; /* OUT: return value for failed entry */
+ } u;
+ uint32_t rsvd; /* IN: padding and must be zero */
+ uint64_t idx; /* IN: resource address to access */
+ uint64_t val; /* IN/OUT: resource value to set/get */
+};
+typedef struct xenpf_resource_entry xenpf_resource_entry_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_resource_entry_t);
+
+struct xenpf_resource_op {
+ uint32_t nr_entries; /* number of resource entry */
+ uint32_t cpu; /* which cpu to run */
+ XEN_GUEST_HANDLE(xenpf_resource_entry_t) entries;
+};
+typedef struct xenpf_resource_op xenpf_resource_op_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_resource_op_t);
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_platform_op(const struct xen_platform_op*);
+ */
+struct xen_platform_op {
+ uint32_t cmd;
+ uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
+ union {
+ struct xenpf_settime settime;
+ struct xenpf_add_memtype add_memtype;
+ struct xenpf_del_memtype del_memtype;
+ struct xenpf_read_memtype read_memtype;
+ struct xenpf_microcode_update microcode;
+ struct xenpf_platform_quirk platform_quirk;
+ struct xenpf_efi_runtime_call efi_runtime_call;
+ struct xenpf_firmware_info firmware_info;
+ struct xenpf_enter_acpi_sleep enter_acpi_sleep;
+ struct xenpf_change_freq change_freq;
+ struct xenpf_getidletime getidletime;
+ struct xenpf_set_processor_pminfo set_pminfo;
+ struct xenpf_pcpuinfo pcpu_info;
+ struct xenpf_pcpu_version pcpu_version;
+ struct xenpf_cpu_ol cpu_ol;
+ struct xenpf_cpu_hotadd cpu_add;
+ struct xenpf_mem_hotadd mem_add;
+ struct xenpf_core_parking core_parking;
+ struct xenpf_resource_op resource_op;
+ uint8_t pad[128];
+ } u;
+};
+typedef struct xen_platform_op xen_platform_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_platform_op_t);
+
+#endif /* __XEN_PUBLIC_PLATFORM_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * sched.h
+ *
+ * Scheduler state interactions
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
+ */
+
+#ifndef __XEN_PUBLIC_SCHED_H__
+#define __XEN_PUBLIC_SCHED_H__
+
+#include "event_channel.h"
+
+/*
+ * `incontents 150 sched Guest Scheduler Operations
+ *
+ * The SCHEDOP interface provides mechanisms for a guest to interact
+ * with the scheduler, including yield, blocking and shutting itself
+ * down.
+ */
+
+/*
+ * The prototype for this hypercall is:
+ * ` long HYPERVISOR_sched_op(enum sched_op cmd, void *arg, ...)
+ *
+ * @cmd == SCHEDOP_??? (scheduler operation).
+ * @arg == Operation-specific extra argument(s), as described below.
+ * ... == Additional Operation-specific extra arguments, described below.
+ *
+ * Versions of Xen prior to 3.0.2 provided only the following legacy version
+ * of this hypercall, supporting only the commands yield, block and shutdown:
+ * long sched_op(int cmd, unsigned long arg)
+ * @cmd == SCHEDOP_??? (scheduler operation).
+ * @arg == 0 (SCHEDOP_yield and SCHEDOP_block)
+ * == SHUTDOWN_* code (SCHEDOP_shutdown)
+ *
+ * This legacy version is available to new guests as:
+ * ` long HYPERVISOR_sched_op_compat(enum sched_op cmd, unsigned long arg)
+ */
+
+/* ` enum sched_op { // SCHEDOP_* => struct sched_* */
+/*
+ * Voluntarily yield the CPU.
+ * @arg == NULL.
+ */
+#define SCHEDOP_yield 0
+
+/*
+ * Block execution of this VCPU until an event is received for processing.
+ * If called with event upcalls masked, this operation will atomically
+ * reenable event delivery and check for pending events before blocking the
+ * VCPU. This avoids a "wakeup waiting" race.
+ * @arg == NULL.
+ */
+#define SCHEDOP_block 1
+
+/*
+ * Halt execution of this domain (all VCPUs) and notify the system controller.
+ * @arg == pointer to sched_shutdown_t structure.
+ *
+ * If the sched_shutdown_t reason is SHUTDOWN_suspend then
+ * x86 PV guests must also set RDX (EDX for 32-bit guests) to the MFN
+ * of the guest's start info page. RDX/EDX is the third hypercall
+ * argument.
+ *
+ * In addition, which reason is SHUTDOWN_suspend this hypercall
+ * returns 1 if suspend was cancelled or the domain was merely
+ * checkpointed, and 0 if it is resuming in a new domain.
+ */
+#define SCHEDOP_shutdown 2
+
+/*
+ * Poll a set of event-channel ports. Return when one or more are pending. An
+ * optional timeout may be specified.
+ * @arg == pointer to sched_poll_t structure.
+ */
+#define SCHEDOP_poll 3
+
+/*
+ * Declare a shutdown for another domain. The main use of this function is
+ * in interpreting shutdown requests and reasons for fully-virtualized
+ * domains. A para-virtualized domain may use SCHEDOP_shutdown directly.
+ * @arg == pointer to sched_remote_shutdown_t structure.
+ */
+#define SCHEDOP_remote_shutdown 4
+
+/*
+ * Latch a shutdown code, so that when the domain later shuts down it
+ * reports this code to the control tools.
+ * @arg == sched_shutdown_t, as for SCHEDOP_shutdown.
+ */
+#define SCHEDOP_shutdown_code 5
+
+/*
+ * Setup, poke and destroy a domain watchdog timer.
+ * @arg == pointer to sched_watchdog_t structure.
+ * With id == 0, setup a domain watchdog timer to cause domain shutdown
+ * after timeout, returns watchdog id.
+ * With id != 0 and timeout == 0, destroy domain watchdog timer.
+ * With id != 0 and timeout != 0, poke watchdog timer and set new timeout.
+ */
+#define SCHEDOP_watchdog 6
+/* ` } */
+
+struct sched_shutdown {
+ unsigned int reason; /* SHUTDOWN_* => enum sched_shutdown_reason */
+};
+typedef struct sched_shutdown sched_shutdown_t;
+DEFINE_XEN_GUEST_HANDLE(sched_shutdown_t);
+
+struct sched_poll {
+ XEN_GUEST_HANDLE(evtchn_port_t) ports;
+ unsigned int nr_ports;
+ uint64_t timeout;
+};
+typedef struct sched_poll sched_poll_t;
+DEFINE_XEN_GUEST_HANDLE(sched_poll_t);
+
+struct sched_remote_shutdown {
+ domid_t domain_id; /* Remote domain ID */
+ unsigned int reason; /* SHUTDOWN_* => enum sched_shutdown_reason */
+};
+typedef struct sched_remote_shutdown sched_remote_shutdown_t;
+DEFINE_XEN_GUEST_HANDLE(sched_remote_shutdown_t);
+
+struct sched_watchdog {
+ uint32_t id; /* watchdog ID */
+ uint32_t timeout; /* timeout */
+};
+typedef struct sched_watchdog sched_watchdog_t;
+DEFINE_XEN_GUEST_HANDLE(sched_watchdog_t);
+
+/*
+ * Reason codes for SCHEDOP_shutdown. These may be interpreted by control
+ * software to determine the appropriate action. For the most part, Xen does
+ * not care about the shutdown code.
+ */
+/* ` enum sched_shutdown_reason { */
+#define SHUTDOWN_poweroff 0 /* Domain exited normally. Clean up and kill. */
+#define SHUTDOWN_reboot 1 /* Clean up, kill, and then restart. */
+#define SHUTDOWN_suspend 2 /* Clean up, save suspend info, kill. */
+#define SHUTDOWN_crash 3 /* Tell controller we've crashed. */
+#define SHUTDOWN_watchdog 4 /* Restart because watchdog time expired. */
+#define SHUTDOWN_MAX 4 /* Maximum valid shutdown reason. */
+/* ` } */
+
+#endif /* __XEN_PUBLIC_SCHED_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * sysctl.h
+ *
+ * System management operations. For use by node control stack.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2002-2006, K Fraser
+ */
+
+#ifndef __XEN_PUBLIC_SYSCTL_H__
+#define __XEN_PUBLIC_SYSCTL_H__
+
+#if !defined(__XEN__) && !defined(__XEN_TOOLS__)
+#error "sysctl operations are intended for use by node control tools only"
+#endif
+
+#include "xen.h"
+#include "domctl.h"
+
+#define XEN_SYSCTL_INTERFACE_VERSION 0x0000000B
+
+/*
+ * Read console content from Xen buffer ring.
+ */
+/* XEN_SYSCTL_readconsole */
+struct xen_sysctl_readconsole {
+ /* IN: Non-zero -> clear after reading. */
+ uint8_t clear;
+ /* IN: Non-zero -> start index specified by @index field. */
+ uint8_t incremental;
+ uint8_t pad0, pad1;
+ /*
+ * IN: Start index for consuming from ring buffer (if @incremental);
+ * OUT: End index after consuming from ring buffer.
+ */
+ uint32_t index;
+ /* IN: Virtual address to write console data. */
+ XEN_GUEST_HANDLE_64(char) buffer;
+ /* IN: Size of buffer; OUT: Bytes written to buffer. */
+ uint32_t count;
+};
+typedef struct xen_sysctl_readconsole xen_sysctl_readconsole_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_readconsole_t);
+
+/* Get trace buffers machine base address */
+/* XEN_SYSCTL_tbuf_op */
+struct xen_sysctl_tbuf_op {
+ /* IN variables */
+#define XEN_SYSCTL_TBUFOP_get_info 0
+#define XEN_SYSCTL_TBUFOP_set_cpu_mask 1
+#define XEN_SYSCTL_TBUFOP_set_evt_mask 2
+#define XEN_SYSCTL_TBUFOP_set_size 3
+#define XEN_SYSCTL_TBUFOP_enable 4
+#define XEN_SYSCTL_TBUFOP_disable 5
+ uint32_t cmd;
+ /* IN/OUT variables */
+ struct xenctl_bitmap cpu_mask;
+ uint32_t evt_mask;
+ /* OUT variables */
+ uint64_aligned_t buffer_mfn;
+ uint32_t size; /* Also an IN variable! */
+};
+typedef struct xen_sysctl_tbuf_op xen_sysctl_tbuf_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_tbuf_op_t);
+
+/*
+ * Get physical information about the host machine
+ */
+/* XEN_SYSCTL_physinfo */
+ /* (x86) The platform supports HVM guests. */
+#define _XEN_SYSCTL_PHYSCAP_hvm 0
+#define XEN_SYSCTL_PHYSCAP_hvm (1u<<_XEN_SYSCTL_PHYSCAP_hvm)
+ /* (x86) The platform supports HVM-guest direct access to I/O devices. */
+#define _XEN_SYSCTL_PHYSCAP_hvm_directio 1
+#define XEN_SYSCTL_PHYSCAP_hvm_directio (1u<<_XEN_SYSCTL_PHYSCAP_hvm_directio)
+struct xen_sysctl_physinfo {
+ uint32_t threads_per_core;
+ uint32_t cores_per_socket;
+ uint32_t nr_cpus; /* # CPUs currently online */
+ uint32_t max_cpu_id; /* Largest possible CPU ID on this host */
+ uint32_t nr_nodes; /* # nodes currently online */
+ uint32_t max_node_id; /* Largest possible node ID on this host */
+ uint32_t cpu_khz;
+ uint64_aligned_t total_pages;
+ uint64_aligned_t free_pages;
+ uint64_aligned_t scrub_pages;
+ uint64_aligned_t outstanding_pages;
+ uint32_t hw_cap[8];
+
+ /* XEN_SYSCTL_PHYSCAP_??? */
+ uint32_t capabilities;
+};
+typedef struct xen_sysctl_physinfo xen_sysctl_physinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_physinfo_t);
+
+/*
+ * Get the ID of the current scheduler.
+ */
+/* XEN_SYSCTL_sched_id */
+struct xen_sysctl_sched_id {
+ /* OUT variable */
+ uint32_t sched_id;
+};
+typedef struct xen_sysctl_sched_id xen_sysctl_sched_id_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_sched_id_t);
+
+/* Interface for controlling Xen software performance counters. */
+/* XEN_SYSCTL_perfc_op */
+/* Sub-operations: */
+#define XEN_SYSCTL_PERFCOP_reset 1 /* Reset all counters to zero. */
+#define XEN_SYSCTL_PERFCOP_query 2 /* Get perfctr information. */
+struct xen_sysctl_perfc_desc {
+ char name[80]; /* name of perf counter */
+ uint32_t nr_vals; /* number of values for this counter */
+};
+typedef struct xen_sysctl_perfc_desc xen_sysctl_perfc_desc_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t);
+typedef uint32_t xen_sysctl_perfc_val_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t);
+
+struct xen_sysctl_perfc_op {
+ /* IN variables. */
+ uint32_t cmd; /* XEN_SYSCTL_PERFCOP_??? */
+ /* OUT variables. */
+ uint32_t nr_counters; /* number of counters description */
+ uint32_t nr_vals; /* number of values */
+ /* counter information (or NULL) */
+ XEN_GUEST_HANDLE_64(xen_sysctl_perfc_desc_t) desc;
+ /* counter values (or NULL) */
+ XEN_GUEST_HANDLE_64(xen_sysctl_perfc_val_t) val;
+};
+typedef struct xen_sysctl_perfc_op xen_sysctl_perfc_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_op_t);
+
+/* XEN_SYSCTL_getdomaininfolist */
+struct xen_sysctl_getdomaininfolist {
+ /* IN variables. */
+ domid_t first_domain;
+ uint32_t max_domains;
+ XEN_GUEST_HANDLE_64(xen_domctl_getdomaininfo_t) buffer;
+ /* OUT variables. */
+ uint32_t num_domains;
+};
+typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t);
+
+/* Inject debug keys into Xen. */
+/* XEN_SYSCTL_debug_keys */
+struct xen_sysctl_debug_keys {
+ /* IN variables. */
+ XEN_GUEST_HANDLE_64(char) keys;
+ uint32_t nr_keys;
+};
+typedef struct xen_sysctl_debug_keys xen_sysctl_debug_keys_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_debug_keys_t);
+
+/* Get physical CPU information. */
+/* XEN_SYSCTL_getcpuinfo */
+struct xen_sysctl_cpuinfo {
+ uint64_aligned_t idletime;
+};
+typedef struct xen_sysctl_cpuinfo xen_sysctl_cpuinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpuinfo_t);
+struct xen_sysctl_getcpuinfo {
+ /* IN variables. */
+ uint32_t max_cpus;
+ XEN_GUEST_HANDLE_64(xen_sysctl_cpuinfo_t) info;
+ /* OUT variables. */
+ uint32_t nr_cpus;
+};
+typedef struct xen_sysctl_getcpuinfo xen_sysctl_getcpuinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getcpuinfo_t);
+
+/* XEN_SYSCTL_availheap */
+struct xen_sysctl_availheap {
+ /* IN variables. */
+ uint32_t min_bitwidth; /* Smallest address width (zero if don't care). */
+ uint32_t max_bitwidth; /* Largest address width (zero if don't care). */
+ int32_t node; /* NUMA node of interest (-1 for all nodes). */
+ /* OUT variables. */
+ uint64_aligned_t avail_bytes;/* Bytes available in the specified region. */
+};
+typedef struct xen_sysctl_availheap xen_sysctl_availheap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_availheap_t);
+
+/* XEN_SYSCTL_get_pmstat */
+struct pm_px_val {
+ uint64_aligned_t freq; /* Px core frequency */
+ uint64_aligned_t residency; /* Px residency time */
+ uint64_aligned_t count; /* Px transition count */
+};
+typedef struct pm_px_val pm_px_val_t;
+DEFINE_XEN_GUEST_HANDLE(pm_px_val_t);
+
+struct pm_px_stat {
+ uint8_t total; /* total Px states */
+ uint8_t usable; /* usable Px states */
+ uint8_t last; /* last Px state */
+ uint8_t cur; /* current Px state */
+ XEN_GUEST_HANDLE_64(uint64) trans_pt; /* Px transition table */
+ XEN_GUEST_HANDLE_64(pm_px_val_t) pt;
+};
+typedef struct pm_px_stat pm_px_stat_t;
+DEFINE_XEN_GUEST_HANDLE(pm_px_stat_t);
+
+struct pm_cx_stat {
+ uint32_t nr; /* entry nr in triggers & residencies, including C0 */
+ uint32_t last; /* last Cx state */
+ uint64_aligned_t idle_time; /* idle time from boot */
+ XEN_GUEST_HANDLE_64(uint64) triggers; /* Cx trigger counts */
+ XEN_GUEST_HANDLE_64(uint64) residencies; /* Cx residencies */
+ uint32_t nr_pc; /* entry nr in pc[] */
+ uint32_t nr_cc; /* entry nr in cc[] */
+ /*
+ * These two arrays may (and generally will) have unused slots; slots not
+ * having a corresponding hardware register will not be written by the
+ * hypervisor. It is therefore up to the caller to put a suitable sentinel
+ * into all slots before invoking the function.
+ * Indexing is 1-biased (PC1/CC1 being at index 0).
+ */
+ XEN_GUEST_HANDLE_64(uint64) pc;
+ XEN_GUEST_HANDLE_64(uint64) cc;
+};
+
+struct xen_sysctl_get_pmstat {
+#define PMSTAT_CATEGORY_MASK 0xf0
+#define PMSTAT_PX 0x10
+#define PMSTAT_CX 0x20
+#define PMSTAT_get_max_px (PMSTAT_PX | 0x1)
+#define PMSTAT_get_pxstat (PMSTAT_PX | 0x2)
+#define PMSTAT_reset_pxstat (PMSTAT_PX | 0x3)
+#define PMSTAT_get_max_cx (PMSTAT_CX | 0x1)
+#define PMSTAT_get_cxstat (PMSTAT_CX | 0x2)
+#define PMSTAT_reset_cxstat (PMSTAT_CX | 0x3)
+ uint32_t type;
+ uint32_t cpuid;
+ union {
+ struct pm_px_stat getpx;
+ struct pm_cx_stat getcx;
+ /* other struct for tx, etc */
+ } u;
+};
+typedef struct xen_sysctl_get_pmstat xen_sysctl_get_pmstat_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_get_pmstat_t);
+
+/* XEN_SYSCTL_cpu_hotplug */
+struct xen_sysctl_cpu_hotplug {
+ /* IN variables */
+ uint32_t cpu; /* Physical cpu. */
+#define XEN_SYSCTL_CPU_HOTPLUG_ONLINE 0
+#define XEN_SYSCTL_CPU_HOTPLUG_OFFLINE 1
+ uint32_t op; /* hotplug opcode */
+};
+typedef struct xen_sysctl_cpu_hotplug xen_sysctl_cpu_hotplug_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpu_hotplug_t);
+
+/*
+ * Get/set xen power management, include
+ * 1. cpufreq governors and related parameters
+ */
+/* XEN_SYSCTL_pm_op */
+struct xen_userspace {
+ uint32_t scaling_setspeed;
+};
+typedef struct xen_userspace xen_userspace_t;
+
+struct xen_ondemand {
+ uint32_t sampling_rate_max;
+ uint32_t sampling_rate_min;
+
+ uint32_t sampling_rate;
+ uint32_t up_threshold;
+};
+typedef struct xen_ondemand xen_ondemand_t;
+
+/*
+ * cpufreq para name of this structure named
+ * same as sysfs file name of native linux
+ */
+#define CPUFREQ_NAME_LEN 16
+struct xen_get_cpufreq_para {
+ /* IN/OUT variable */
+ uint32_t cpu_num;
+ uint32_t freq_num;
+ uint32_t gov_num;
+
+ /* for all governors */
+ /* OUT variable */
+ XEN_GUEST_HANDLE_64(uint32) affected_cpus;
+ XEN_GUEST_HANDLE_64(uint32) scaling_available_frequencies;
+ XEN_GUEST_HANDLE_64(char) scaling_available_governors;
+ char scaling_driver[CPUFREQ_NAME_LEN];
+
+ uint32_t cpuinfo_cur_freq;
+ uint32_t cpuinfo_max_freq;
+ uint32_t cpuinfo_min_freq;
+ uint32_t scaling_cur_freq;
+
+ char scaling_governor[CPUFREQ_NAME_LEN];
+ uint32_t scaling_max_freq;
+ uint32_t scaling_min_freq;
+
+ /* for specific governor */
+ union {
+ struct xen_userspace userspace;
+ struct xen_ondemand ondemand;
+ } u;
+
+ int32_t turbo_enabled;
+};
+
+struct xen_set_cpufreq_gov {
+ char scaling_governor[CPUFREQ_NAME_LEN];
+};
+
+struct xen_set_cpufreq_para {
+ #define SCALING_MAX_FREQ 1
+ #define SCALING_MIN_FREQ 2
+ #define SCALING_SETSPEED 3
+ #define SAMPLING_RATE 4
+ #define UP_THRESHOLD 5
+
+ uint32_t ctrl_type;
+ uint32_t ctrl_value;
+};
+
+struct xen_sysctl_pm_op {
+ #define PM_PARA_CATEGORY_MASK 0xf0
+ #define CPUFREQ_PARA 0x10
+
+ /* cpufreq command type */
+ #define GET_CPUFREQ_PARA (CPUFREQ_PARA | 0x01)
+ #define SET_CPUFREQ_GOV (CPUFREQ_PARA | 0x02)
+ #define SET_CPUFREQ_PARA (CPUFREQ_PARA | 0x03)
+ #define GET_CPUFREQ_AVGFREQ (CPUFREQ_PARA | 0x04)
+
+ /* set/reset scheduler power saving option */
+ #define XEN_SYSCTL_pm_op_set_sched_opt_smt 0x21
+
+ /* cpuidle max_cstate access command */
+ #define XEN_SYSCTL_pm_op_get_max_cstate 0x22
+ #define XEN_SYSCTL_pm_op_set_max_cstate 0x23
+
+ /* set scheduler migration cost value */
+ #define XEN_SYSCTL_pm_op_set_vcpu_migration_delay 0x24
+ #define XEN_SYSCTL_pm_op_get_vcpu_migration_delay 0x25
+
+ /* enable/disable turbo mode when in dbs governor */
+ #define XEN_SYSCTL_pm_op_enable_turbo 0x26
+ #define XEN_SYSCTL_pm_op_disable_turbo 0x27
+
+ uint32_t cmd;
+ uint32_t cpuid;
+ union {
+ struct xen_get_cpufreq_para get_para;
+ struct xen_set_cpufreq_gov set_gov;
+ struct xen_set_cpufreq_para set_para;
+ uint64_aligned_t get_avgfreq;
+ uint32_t set_sched_opt_smt;
+ uint32_t get_max_cstate;
+ uint32_t set_max_cstate;
+ uint32_t get_vcpu_migration_delay;
+ uint32_t set_vcpu_migration_delay;
+ } u;
+};
+
+/* XEN_SYSCTL_page_offline_op */
+struct xen_sysctl_page_offline_op {
+ /* IN: range of page to be offlined */
+#define sysctl_page_offline 1
+#define sysctl_page_online 2
+#define sysctl_query_page_offline 3
+ uint32_t cmd;
+ uint32_t start;
+ uint32_t end;
+ /* OUT: result of page offline request */
+ /*
+ * bit 0~15: result flags
+ * bit 16~31: owner
+ */
+ XEN_GUEST_HANDLE(uint32) status;
+};
+
+#define PG_OFFLINE_STATUS_MASK (0xFFUL)
+
+/* The result is invalid, i.e. HV does not handle it */
+#define PG_OFFLINE_INVALID (0x1UL << 0)
+
+#define PG_OFFLINE_OFFLINED (0x1UL << 1)
+#define PG_OFFLINE_PENDING (0x1UL << 2)
+#define PG_OFFLINE_FAILED (0x1UL << 3)
+#define PG_OFFLINE_AGAIN (0x1UL << 4)
+
+#define PG_ONLINE_FAILED PG_OFFLINE_FAILED
+#define PG_ONLINE_ONLINED PG_OFFLINE_OFFLINED
+
+#define PG_OFFLINE_STATUS_OFFLINED (0x1UL << 1)
+#define PG_OFFLINE_STATUS_ONLINE (0x1UL << 2)
+#define PG_OFFLINE_STATUS_OFFLINE_PENDING (0x1UL << 3)
+#define PG_OFFLINE_STATUS_BROKEN (0x1UL << 4)
+
+#define PG_OFFLINE_MISC_MASK (0xFFUL << 4)
+
+/* valid when PG_OFFLINE_FAILED or PG_OFFLINE_PENDING */
+#define PG_OFFLINE_XENPAGE (0x1UL << 8)
+#define PG_OFFLINE_DOM0PAGE (0x1UL << 9)
+#define PG_OFFLINE_ANONYMOUS (0x1UL << 10)
+#define PG_OFFLINE_NOT_CONV_RAM (0x1UL << 11)
+#define PG_OFFLINE_OWNED (0x1UL << 12)
+
+#define PG_OFFLINE_BROKEN (0x1UL << 13)
+#define PG_ONLINE_BROKEN PG_OFFLINE_BROKEN
+
+#define PG_OFFLINE_OWNER_SHIFT 16
+
+/* XEN_SYSCTL_lockprof_op */
+/* Sub-operations: */
+#define XEN_SYSCTL_LOCKPROF_reset 1 /* Reset all profile data to zero. */
+#define XEN_SYSCTL_LOCKPROF_query 2 /* Get lock profile information. */
+/* Record-type: */
+#define LOCKPROF_TYPE_GLOBAL 0 /* global lock, idx meaningless */
+#define LOCKPROF_TYPE_PERDOM 1 /* per-domain lock, idx is domid */
+#define LOCKPROF_TYPE_N 2 /* number of types */
+struct xen_sysctl_lockprof_data {
+ char name[40]; /* lock name (may include up to 2 %d specifiers) */
+ int32_t type; /* LOCKPROF_TYPE_??? */
+ int32_t idx; /* index (e.g. domain id) */
+ uint64_aligned_t lock_cnt; /* # of locking succeeded */
+ uint64_aligned_t block_cnt; /* # of wait for lock */
+ uint64_aligned_t lock_time; /* nsecs lock held */
+ uint64_aligned_t block_time; /* nsecs waited for lock */
+};
+typedef struct xen_sysctl_lockprof_data xen_sysctl_lockprof_data_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_lockprof_data_t);
+struct xen_sysctl_lockprof_op {
+ /* IN variables. */
+ uint32_t cmd; /* XEN_SYSCTL_LOCKPROF_??? */
+ uint32_t max_elem; /* size of output buffer */
+ /* OUT variables (query only). */
+ uint32_t nr_elem; /* number of elements available */
+ uint64_aligned_t time; /* nsecs of profile measurement */
+ /* profile information (or NULL) */
+ XEN_GUEST_HANDLE_64(xen_sysctl_lockprof_data_t) data;
+};
+typedef struct xen_sysctl_lockprof_op xen_sysctl_lockprof_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_lockprof_op_t);
+
+/* XEN_SYSCTL_topologyinfo */
+#define INVALID_TOPOLOGY_ID (~0U)
+struct xen_sysctl_topologyinfo {
+ /*
+ * IN: maximum addressable entry in the caller-provided arrays.
+ * OUT: largest cpu identifier in the system.
+ * If OUT is greater than IN then the arrays are truncated!
+ * If OUT is leass than IN then the array tails are not written by sysctl.
+ */
+ uint32_t max_cpu_index;
+
+ /*
+ * If not NULL, these arrays are filled with core/socket/node identifier
+ * for each cpu.
+ * If a cpu has no core/socket/node information (e.g., cpu not present)
+ * then the sentinel value ~0u is written to each array.
+ * The number of array elements written by the sysctl is:
+ * min(@max_cpu_index_IN,@max_cpu_index_OUT)+1
+ */
+ XEN_GUEST_HANDLE_64(uint32) cpu_to_core;
+ XEN_GUEST_HANDLE_64(uint32) cpu_to_socket;
+ XEN_GUEST_HANDLE_64(uint32) cpu_to_node;
+};
+typedef struct xen_sysctl_topologyinfo xen_sysctl_topologyinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_topologyinfo_t);
+
+/* XEN_SYSCTL_numainfo */
+#define INVALID_NUMAINFO_ID (~0U)
+struct xen_sysctl_numainfo {
+ /*
+ * IN: maximum addressable entry in the caller-provided arrays.
+ * OUT: largest node identifier in the system.
+ * If OUT is greater than IN then the arrays are truncated!
+ */
+ uint32_t max_node_index;
+
+ /* NB. Entries are 0 if node is not present. */
+ XEN_GUEST_HANDLE_64(uint64) node_to_memsize;
+ XEN_GUEST_HANDLE_64(uint64) node_to_memfree;
+
+ /*
+ * Array, of size (max_node_index+1)^2, listing memory access distances
+ * between nodes. If an entry has no node distance information (e.g., node
+ * not present) then the value ~0u is written.
+ *
+ * Note that the array rows must be indexed by multiplying by the minimum
+ * of the caller-provided max_node_index and the returned value of
+ * max_node_index. That is, if the largest node index in the system is
+ * smaller than the caller can handle, a smaller 2-d array is constructed
+ * within the space provided by the caller. When this occurs, trailing
+ * space provided by the caller is not modified. If the largest node index
+ * in the system is larger than the caller can handle, then a 2-d array of
+ * the maximum size handleable by the caller is constructed.
+ */
+ XEN_GUEST_HANDLE_64(uint32) node_to_node_distance;
+};
+typedef struct xen_sysctl_numainfo xen_sysctl_numainfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_numainfo_t);
+
+/* XEN_SYSCTL_cpupool_op */
+#define XEN_SYSCTL_CPUPOOL_OP_CREATE 1 /* C */
+#define XEN_SYSCTL_CPUPOOL_OP_DESTROY 2 /* D */
+#define XEN_SYSCTL_CPUPOOL_OP_INFO 3 /* I */
+#define XEN_SYSCTL_CPUPOOL_OP_ADDCPU 4 /* A */
+#define XEN_SYSCTL_CPUPOOL_OP_RMCPU 5 /* R */
+#define XEN_SYSCTL_CPUPOOL_OP_MOVEDOMAIN 6 /* M */
+#define XEN_SYSCTL_CPUPOOL_OP_FREEINFO 7 /* F */
+#define XEN_SYSCTL_CPUPOOL_PAR_ANY 0xFFFFFFFF
+struct xen_sysctl_cpupool_op {
+ uint32_t op; /* IN */
+ uint32_t cpupool_id; /* IN: CDIARM OUT: CI */
+ uint32_t sched_id; /* IN: C OUT: I */
+ uint32_t domid; /* IN: M */
+ uint32_t cpu; /* IN: AR */
+ uint32_t n_dom; /* OUT: I */
+ struct xenctl_bitmap cpumap; /* OUT: IF */
+};
+typedef struct xen_sysctl_cpupool_op xen_sysctl_cpupool_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpupool_op_t);
+
+#define ARINC653_MAX_DOMAINS_PER_SCHEDULE 64
+/*
+ * This structure is used to pass a new ARINC653 schedule from a
+ * privileged domain (ie dom0) to Xen.
+ */
+struct xen_sysctl_arinc653_schedule {
+ /* major_frame holds the time for the new schedule's major frame
+ * in nanoseconds. */
+ uint64_aligned_t major_frame;
+ /* num_sched_entries holds how many of the entries in the
+ * sched_entries[] array are valid. */
+ uint8_t num_sched_entries;
+ /* The sched_entries array holds the actual schedule entries. */
+ struct {
+ /* dom_handle must match a domain's UUID */
+ xen_domain_handle_t dom_handle;
+ /* If a domain has multiple VCPUs, vcpu_id specifies which one
+ * this schedule entry applies to. It should be set to 0 if
+ * there is only one VCPU for the domain. */
+ unsigned int vcpu_id;
+ /* runtime specifies the amount of time that should be allocated
+ * to this VCPU per major frame. It is specified in nanoseconds */
+ uint64_aligned_t runtime;
+ } sched_entries[ARINC653_MAX_DOMAINS_PER_SCHEDULE];
+};
+typedef struct xen_sysctl_arinc653_schedule xen_sysctl_arinc653_schedule_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_arinc653_schedule_t);
+
+struct xen_sysctl_credit_schedule {
+ /* Length of timeslice in milliseconds */
+#define XEN_SYSCTL_CSCHED_TSLICE_MAX 1000
+#define XEN_SYSCTL_CSCHED_TSLICE_MIN 1
+ unsigned tslice_ms;
+ /* Rate limit (minimum timeslice) in microseconds */
+#define XEN_SYSCTL_SCHED_RATELIMIT_MAX 500000
+#define XEN_SYSCTL_SCHED_RATELIMIT_MIN 100
+ unsigned ratelimit_us;
+};
+typedef struct xen_sysctl_credit_schedule xen_sysctl_credit_schedule_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_credit_schedule_t);
+
+/* XEN_SYSCTL_scheduler_op */
+/* Set or get info? */
+#define XEN_SYSCTL_SCHEDOP_putinfo 0
+#define XEN_SYSCTL_SCHEDOP_getinfo 1
+struct xen_sysctl_scheduler_op {
+ uint32_t cpupool_id; /* Cpupool whose scheduler is to be targetted. */
+ uint32_t sched_id; /* XEN_SCHEDULER_* (domctl.h) */
+ uint32_t cmd; /* XEN_SYSCTL_SCHEDOP_* */
+ union {
+ struct xen_sysctl_sched_arinc653 {
+ XEN_GUEST_HANDLE_64(xen_sysctl_arinc653_schedule_t) schedule;
+ } sched_arinc653;
+ struct xen_sysctl_credit_schedule sched_credit;
+ } u;
+};
+typedef struct xen_sysctl_scheduler_op xen_sysctl_scheduler_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_scheduler_op_t);
+
+/* XEN_SYSCTL_coverage_op */
+/*
+ * Get total size of information, to help allocate
+ * the buffer. The pointer points to a 32 bit value.
+ */
+#define XEN_SYSCTL_COVERAGE_get_total_size 0
+
+/*
+ * Read coverage information in a single run
+ * You must use a tool to split them.
+ */
+#define XEN_SYSCTL_COVERAGE_read 1
+
+/*
+ * Reset all the coverage counters to 0
+ * No parameters.
+ */
+#define XEN_SYSCTL_COVERAGE_reset 2
+
+/*
+ * Like XEN_SYSCTL_COVERAGE_read but reset also
+ * counters to 0 in a single call.
+ */
+#define XEN_SYSCTL_COVERAGE_read_and_reset 3
+
+struct xen_sysctl_coverage_op {
+ uint32_t cmd; /* XEN_SYSCTL_COVERAGE_* */
+ union {
+ uint32_t total_size; /* OUT */
+ XEN_GUEST_HANDLE_64(uint8) raw_info; /* OUT */
+ } u;
+};
+typedef struct xen_sysctl_coverage_op xen_sysctl_coverage_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_coverage_op_t);
+
+#define XEN_SYSCTL_PSR_CMT_get_total_rmid 0
+#define XEN_SYSCTL_PSR_CMT_get_l3_upscaling_factor 1
+/* The L3 cache size is returned in KB unit */
+#define XEN_SYSCTL_PSR_CMT_get_l3_cache_size 2
+#define XEN_SYSCTL_PSR_CMT_enabled 3
+#define XEN_SYSCTL_PSR_CMT_get_l3_event_mask 4
+struct xen_sysctl_psr_cmt_op {
+ uint32_t cmd; /* IN: XEN_SYSCTL_PSR_CMT_* */
+ uint32_t flags; /* padding variable, may be extended for future use */
+ union {
+ uint64_t data; /* OUT */
+ struct {
+ uint32_t cpu; /* IN */
+ uint32_t rsvd;
+ } l3_cache;
+ } u;
+};
+typedef struct xen_sysctl_psr_cmt_op xen_sysctl_psr_cmt_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_psr_cmt_op_t);
+
+struct xen_sysctl {
+ uint32_t cmd;
+#define XEN_SYSCTL_readconsole 1
+#define XEN_SYSCTL_tbuf_op 2
+#define XEN_SYSCTL_physinfo 3
+#define XEN_SYSCTL_sched_id 4
+#define XEN_SYSCTL_perfc_op 5
+#define XEN_SYSCTL_getdomaininfolist 6
+#define XEN_SYSCTL_debug_keys 7
+#define XEN_SYSCTL_getcpuinfo 8
+#define XEN_SYSCTL_availheap 9
+#define XEN_SYSCTL_get_pmstat 10
+#define XEN_SYSCTL_cpu_hotplug 11
+#define XEN_SYSCTL_pm_op 12
+#define XEN_SYSCTL_page_offline_op 14
+#define XEN_SYSCTL_lockprof_op 15
+#define XEN_SYSCTL_topologyinfo 16
+#define XEN_SYSCTL_numainfo 17
+#define XEN_SYSCTL_cpupool_op 18
+#define XEN_SYSCTL_scheduler_op 19
+#define XEN_SYSCTL_coverage_op 20
+#define XEN_SYSCTL_psr_cmt_op 21
+ uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
+ union {
+ struct xen_sysctl_readconsole readconsole;
+ struct xen_sysctl_tbuf_op tbuf_op;
+ struct xen_sysctl_physinfo physinfo;
+ struct xen_sysctl_topologyinfo topologyinfo;
+ struct xen_sysctl_numainfo numainfo;
+ struct xen_sysctl_sched_id sched_id;
+ struct xen_sysctl_perfc_op perfc_op;
+ struct xen_sysctl_getdomaininfolist getdomaininfolist;
+ struct xen_sysctl_debug_keys debug_keys;
+ struct xen_sysctl_getcpuinfo getcpuinfo;
+ struct xen_sysctl_availheap availheap;
+ struct xen_sysctl_get_pmstat get_pmstat;
+ struct xen_sysctl_cpu_hotplug cpu_hotplug;
+ struct xen_sysctl_pm_op pm_op;
+ struct xen_sysctl_page_offline_op page_offline;
+ struct xen_sysctl_lockprof_op lockprof_op;
+ struct xen_sysctl_cpupool_op cpupool_op;
+ struct xen_sysctl_scheduler_op scheduler_op;
+ struct xen_sysctl_coverage_op coverage_op;
+ struct xen_sysctl_psr_cmt_op psr_cmt_op;
+ uint8_t pad[128];
+ } u;
+};
+typedef struct xen_sysctl xen_sysctl_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_t);
+
+#endif /* __XEN_PUBLIC_SYSCTL_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * tmem.h
+ *
+ * Guest OS interface to Xen Transcendent Memory.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#ifndef __XEN_PUBLIC_TMEM_H__
+#define __XEN_PUBLIC_TMEM_H__
+
+#include "xen.h"
+
+/* version of ABI */
+#define TMEM_SPEC_VERSION 1
+
+/* Commands to HYPERVISOR_tmem_op() */
+#define TMEM_CONTROL 0
+#define TMEM_NEW_POOL 1
+#define TMEM_DESTROY_POOL 2
+#define TMEM_PUT_PAGE 4
+#define TMEM_GET_PAGE 5
+#define TMEM_FLUSH_PAGE 6
+#define TMEM_FLUSH_OBJECT 7
+#if __XEN_INTERFACE_VERSION__ < 0x00040400
+#define TMEM_NEW_PAGE 3
+#define TMEM_READ 8
+#define TMEM_WRITE 9
+#define TMEM_XCHG 10
+#endif
+
+/* Privileged commands to HYPERVISOR_tmem_op() */
+#define TMEM_AUTH 101
+#define TMEM_RESTORE_NEW 102
+
+/* Subops for HYPERVISOR_tmem_op(TMEM_CONTROL) */
+#define TMEMC_THAW 0
+#define TMEMC_FREEZE 1
+#define TMEMC_FLUSH 2
+#define TMEMC_DESTROY 3
+#define TMEMC_LIST 4
+#define TMEMC_SET_WEIGHT 5
+#define TMEMC_SET_CAP 6
+#define TMEMC_SET_COMPRESS 7
+#define TMEMC_QUERY_FREEABLE_MB 8
+#define TMEMC_SAVE_BEGIN 10
+#define TMEMC_SAVE_GET_VERSION 11
+#define TMEMC_SAVE_GET_MAXPOOLS 12
+#define TMEMC_SAVE_GET_CLIENT_WEIGHT 13
+#define TMEMC_SAVE_GET_CLIENT_CAP 14
+#define TMEMC_SAVE_GET_CLIENT_FLAGS 15
+#define TMEMC_SAVE_GET_POOL_FLAGS 16
+#define TMEMC_SAVE_GET_POOL_NPAGES 17
+#define TMEMC_SAVE_GET_POOL_UUID 18
+#define TMEMC_SAVE_GET_NEXT_PAGE 19
+#define TMEMC_SAVE_GET_NEXT_INV 20
+#define TMEMC_SAVE_END 21
+#define TMEMC_RESTORE_BEGIN 30
+#define TMEMC_RESTORE_PUT_PAGE 32
+#define TMEMC_RESTORE_FLUSH_PAGE 33
+
+/* Bits for HYPERVISOR_tmem_op(TMEM_NEW_POOL) */
+#define TMEM_POOL_PERSIST 1
+#define TMEM_POOL_SHARED 2
+#define TMEM_POOL_PRECOMPRESSED 4
+#define TMEM_POOL_PAGESIZE_SHIFT 4
+#define TMEM_POOL_PAGESIZE_MASK 0xf
+#define TMEM_POOL_VERSION_SHIFT 24
+#define TMEM_POOL_VERSION_MASK 0xff
+#define TMEM_POOL_RESERVED_BITS 0x00ffff00
+
+/* Bits for client flags (save/restore) */
+#define TMEM_CLIENT_COMPRESS 1
+#define TMEM_CLIENT_FROZEN 2
+
+/* Special errno values */
+#define EFROZEN 1000
+#define EEMPTY 1001
+
+
+#ifndef __ASSEMBLY__
+#if __XEN_INTERFACE_VERSION__ < 0x00040400
+typedef xen_pfn_t tmem_cli_mfn_t;
+#endif
+typedef XEN_GUEST_HANDLE(char) tmem_cli_va_t;
+struct tmem_op {
+ uint32_t cmd;
+ int32_t pool_id;
+ union {
+ struct {
+ uint64_t uuid[2];
+ uint32_t flags;
+ uint32_t arg1;
+ } creat; /* for cmd == TMEM_NEW_POOL, TMEM_AUTH, TMEM_RESTORE_NEW */
+ struct {
+ uint32_t subop;
+ uint32_t cli_id;
+ uint32_t arg1;
+ uint32_t arg2;
+ uint64_t oid[3];
+ tmem_cli_va_t buf;
+ } ctrl; /* for cmd == TMEM_CONTROL */
+ struct {
+
+ uint64_t oid[3];
+ uint32_t index;
+ uint32_t tmem_offset;
+ uint32_t pfn_offset;
+ uint32_t len;
+ xen_pfn_t cmfn; /* client machine page frame */
+ } gen; /* for all other cmd ("generic") */
+ } u;
+};
+typedef struct tmem_op tmem_op_t;
+DEFINE_XEN_GUEST_HANDLE(tmem_op_t);
+
+struct tmem_handle {
+ uint32_t pool_id;
+ uint32_t index;
+ uint64_t oid[3];
+};
+#endif
+
+#endif /* __XEN_PUBLIC_TMEM_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * include/public/trace.h
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Mark Williamson, (C) 2004 Intel Research Cambridge
+ * Copyright (C) 2005 Bin Ren
+ */
+
+#ifndef __XEN_PUBLIC_TRACE_H__
+#define __XEN_PUBLIC_TRACE_H__
+
+#define TRACE_EXTRA_MAX 7
+#define TRACE_EXTRA_SHIFT 28
+
+/* Trace classes */
+#define TRC_CLS_SHIFT 16
+#define TRC_GEN 0x0001f000 /* General trace */
+#define TRC_SCHED 0x0002f000 /* Xen Scheduler trace */
+#define TRC_DOM0OP 0x0004f000 /* Xen DOM0 operation trace */
+#define TRC_HVM 0x0008f000 /* Xen HVM trace */
+#define TRC_MEM 0x0010f000 /* Xen memory trace */
+#define TRC_PV 0x0020f000 /* Xen PV traces */
+#define TRC_SHADOW 0x0040f000 /* Xen shadow tracing */
+#define TRC_HW 0x0080f000 /* Xen hardware-related traces */
+#define TRC_GUEST 0x0800f000 /* Guest-generated traces */
+#define TRC_ALL 0x0ffff000
+#define TRC_HD_TO_EVENT(x) ((x)&0x0fffffff)
+#define TRC_HD_CYCLE_FLAG (1UL<<31)
+#define TRC_HD_INCLUDES_CYCLE_COUNT(x) ( !!( (x) & TRC_HD_CYCLE_FLAG ) )
+#define TRC_HD_EXTRA(x) (((x)>>TRACE_EXTRA_SHIFT)&TRACE_EXTRA_MAX)
+
+/* Trace subclasses */
+#define TRC_SUBCLS_SHIFT 12
+
+/* trace subclasses for SVM */
+#define TRC_HVM_ENTRYEXIT 0x00081000 /* VMENTRY and #VMEXIT */
+#define TRC_HVM_HANDLER 0x00082000 /* various HVM handlers */
+#define TRC_HVM_EMUL 0x00084000 /* emulated devices */
+
+#define TRC_SCHED_MIN 0x00021000 /* Just runstate changes */
+#define TRC_SCHED_CLASS 0x00022000 /* Scheduler-specific */
+#define TRC_SCHED_VERBOSE 0x00028000 /* More inclusive scheduling */
+
+/*
+ * The highest 3 bits of the last 12 bits of TRC_SCHED_CLASS above are
+ * reserved for encoding what scheduler produced the information. The
+ * actual event is encoded in the last 9 bits.
+ *
+ * This means we have 8 scheduling IDs available (which means at most 8
+ * schedulers generating events) and, in each scheduler, up to 512
+ * different events.
+ */
+#define TRC_SCHED_ID_BITS 3
+#define TRC_SCHED_ID_SHIFT (TRC_SUBCLS_SHIFT - TRC_SCHED_ID_BITS)
+#define TRC_SCHED_ID_MASK (((1UL<<TRC_SCHED_ID_BITS) - 1) << TRC_SCHED_ID_SHIFT)
+#define TRC_SCHED_EVT_MASK (~(TRC_SCHED_ID_MASK))
+
+/* Per-scheduler IDs, to identify scheduler specific events */
+#define TRC_SCHED_CSCHED 0
+#define TRC_SCHED_CSCHED2 1
+#define TRC_SCHED_SEDF 2
+#define TRC_SCHED_ARINC653 3
+#define TRC_SCHED_RTDS 4
+
+/* Per-scheduler tracing */
+#define TRC_SCHED_CLASS_EVT(_c, _e) \
+ ( ( TRC_SCHED_CLASS | \
+ ((TRC_SCHED_##_c << TRC_SCHED_ID_SHIFT) & TRC_SCHED_ID_MASK) ) + \
+ (_e & TRC_SCHED_EVT_MASK) )
+
+/* Trace classes for Hardware */
+#define TRC_HW_PM 0x00801000 /* Power management traces */
+#define TRC_HW_IRQ 0x00802000 /* Traces relating to the handling of IRQs */
+
+/* Trace events per class */
+#define TRC_LOST_RECORDS (TRC_GEN + 1)
+#define TRC_TRACE_WRAP_BUFFER (TRC_GEN + 2)
+#define TRC_TRACE_CPU_CHANGE (TRC_GEN + 3)
+
+#define TRC_SCHED_RUNSTATE_CHANGE (TRC_SCHED_MIN + 1)
+#define TRC_SCHED_CONTINUE_RUNNING (TRC_SCHED_MIN + 2)
+#define TRC_SCHED_DOM_ADD (TRC_SCHED_VERBOSE + 1)
+#define TRC_SCHED_DOM_REM (TRC_SCHED_VERBOSE + 2)
+#define TRC_SCHED_SLEEP (TRC_SCHED_VERBOSE + 3)
+#define TRC_SCHED_WAKE (TRC_SCHED_VERBOSE + 4)
+#define TRC_SCHED_YIELD (TRC_SCHED_VERBOSE + 5)
+#define TRC_SCHED_BLOCK (TRC_SCHED_VERBOSE + 6)
+#define TRC_SCHED_SHUTDOWN (TRC_SCHED_VERBOSE + 7)
+#define TRC_SCHED_CTL (TRC_SCHED_VERBOSE + 8)
+#define TRC_SCHED_ADJDOM (TRC_SCHED_VERBOSE + 9)
+#define TRC_SCHED_SWITCH (TRC_SCHED_VERBOSE + 10)
+#define TRC_SCHED_S_TIMER_FN (TRC_SCHED_VERBOSE + 11)
+#define TRC_SCHED_T_TIMER_FN (TRC_SCHED_VERBOSE + 12)
+#define TRC_SCHED_DOM_TIMER_FN (TRC_SCHED_VERBOSE + 13)
+#define TRC_SCHED_SWITCH_INFPREV (TRC_SCHED_VERBOSE + 14)
+#define TRC_SCHED_SWITCH_INFNEXT (TRC_SCHED_VERBOSE + 15)
+#define TRC_SCHED_SHUTDOWN_CODE (TRC_SCHED_VERBOSE + 16)
+
+#define TRC_MEM_PAGE_GRANT_MAP (TRC_MEM + 1)
+#define TRC_MEM_PAGE_GRANT_UNMAP (TRC_MEM + 2)
+#define TRC_MEM_PAGE_GRANT_TRANSFER (TRC_MEM + 3)
+#define TRC_MEM_SET_P2M_ENTRY (TRC_MEM + 4)
+#define TRC_MEM_DECREASE_RESERVATION (TRC_MEM + 5)
+#define TRC_MEM_POD_POPULATE (TRC_MEM + 16)
+#define TRC_MEM_POD_ZERO_RECLAIM (TRC_MEM + 17)
+#define TRC_MEM_POD_SUPERPAGE_SPLINTER (TRC_MEM + 18)
+
+#define TRC_PV_ENTRY 0x00201000 /* Hypervisor entry points for PV guests. */
+#define TRC_PV_SUBCALL 0x00202000 /* Sub-call in a multicall hypercall */
+
+#define TRC_PV_HYPERCALL (TRC_PV_ENTRY + 1)
+#define TRC_PV_TRAP (TRC_PV_ENTRY + 3)
+#define TRC_PV_PAGE_FAULT (TRC_PV_ENTRY + 4)
+#define TRC_PV_FORCED_INVALID_OP (TRC_PV_ENTRY + 5)
+#define TRC_PV_EMULATE_PRIVOP (TRC_PV_ENTRY + 6)
+#define TRC_PV_EMULATE_4GB (TRC_PV_ENTRY + 7)
+#define TRC_PV_MATH_STATE_RESTORE (TRC_PV_ENTRY + 8)
+#define TRC_PV_PAGING_FIXUP (TRC_PV_ENTRY + 9)
+#define TRC_PV_GDT_LDT_MAPPING_FAULT (TRC_PV_ENTRY + 10)
+#define TRC_PV_PTWR_EMULATION (TRC_PV_ENTRY + 11)
+#define TRC_PV_PTWR_EMULATION_PAE (TRC_PV_ENTRY + 12)
+#define TRC_PV_HYPERCALL_V2 (TRC_PV_ENTRY + 13)
+#define TRC_PV_HYPERCALL_SUBCALL (TRC_PV_SUBCALL + 14)
+
+/*
+ * TRC_PV_HYPERCALL_V2 format
+ *
+ * Only some of the hypercall argument are recorded. Bit fields A0 to
+ * A5 in the first extra word are set if the argument is present and
+ * the arguments themselves are packed sequentially in the following
+ * words.
+ *
+ * The TRC_64_FLAG bit is not set for these events (even if there are
+ * 64-bit arguments in the record).
+ *
+ * Word
+ * 0 bit 31 30|29 28|27 26|25 24|23 22|21 20|19 ... 0
+ * A5 |A4 |A3 |A2 |A1 |A0 |Hypercall op
+ * 1 First 32 bit (or low word of first 64 bit) arg in record
+ * 2 Second 32 bit (or high word of first 64 bit) arg in record
+ * ...
+ *
+ * A0-A5 bitfield values:
+ *
+ * 00b Argument not present
+ * 01b 32-bit argument present
+ * 10b 64-bit argument present
+ * 11b Reserved
+ */
+#define TRC_PV_HYPERCALL_V2_ARG_32(i) (0x1 << (20 + 2*(i)))
+#define TRC_PV_HYPERCALL_V2_ARG_64(i) (0x2 << (20 + 2*(i)))
+#define TRC_PV_HYPERCALL_V2_ARG_MASK (0xfff00000)
+
+#define TRC_SHADOW_NOT_SHADOW (TRC_SHADOW + 1)
+#define TRC_SHADOW_FAST_PROPAGATE (TRC_SHADOW + 2)
+#define TRC_SHADOW_FAST_MMIO (TRC_SHADOW + 3)
+#define TRC_SHADOW_FALSE_FAST_PATH (TRC_SHADOW + 4)
+#define TRC_SHADOW_MMIO (TRC_SHADOW + 5)
+#define TRC_SHADOW_FIXUP (TRC_SHADOW + 6)
+#define TRC_SHADOW_DOMF_DYING (TRC_SHADOW + 7)
+#define TRC_SHADOW_EMULATE (TRC_SHADOW + 8)
+#define TRC_SHADOW_EMULATE_UNSHADOW_USER (TRC_SHADOW + 9)
+#define TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ (TRC_SHADOW + 10)
+#define TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED (TRC_SHADOW + 11)
+#define TRC_SHADOW_WRMAP_BF (TRC_SHADOW + 12)
+#define TRC_SHADOW_PREALLOC_UNPIN (TRC_SHADOW + 13)
+#define TRC_SHADOW_RESYNC_FULL (TRC_SHADOW + 14)
+#define TRC_SHADOW_RESYNC_ONLY (TRC_SHADOW + 15)
+
+/* trace events per subclass */
+#define TRC_HVM_NESTEDFLAG (0x400)
+#define TRC_HVM_VMENTRY (TRC_HVM_ENTRYEXIT + 0x01)
+#define TRC_HVM_VMEXIT (TRC_HVM_ENTRYEXIT + 0x02)
+#define TRC_HVM_VMEXIT64 (TRC_HVM_ENTRYEXIT + TRC_64_FLAG + 0x02)
+#define TRC_HVM_PF_XEN (TRC_HVM_HANDLER + 0x01)
+#define TRC_HVM_PF_XEN64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x01)
+#define TRC_HVM_PF_INJECT (TRC_HVM_HANDLER + 0x02)
+#define TRC_HVM_PF_INJECT64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x02)
+#define TRC_HVM_INJ_EXC (TRC_HVM_HANDLER + 0x03)
+#define TRC_HVM_INJ_VIRQ (TRC_HVM_HANDLER + 0x04)
+#define TRC_HVM_REINJ_VIRQ (TRC_HVM_HANDLER + 0x05)
+#define TRC_HVM_IO_READ (TRC_HVM_HANDLER + 0x06)
+#define TRC_HVM_IO_WRITE (TRC_HVM_HANDLER + 0x07)
+#define TRC_HVM_CR_READ (TRC_HVM_HANDLER + 0x08)
+#define TRC_HVM_CR_READ64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x08)
+#define TRC_HVM_CR_WRITE (TRC_HVM_HANDLER + 0x09)
+#define TRC_HVM_CR_WRITE64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x09)
+#define TRC_HVM_DR_READ (TRC_HVM_HANDLER + 0x0A)
+#define TRC_HVM_DR_WRITE (TRC_HVM_HANDLER + 0x0B)
+#define TRC_HVM_MSR_READ (TRC_HVM_HANDLER + 0x0C)
+#define TRC_HVM_MSR_WRITE (TRC_HVM_HANDLER + 0x0D)
+#define TRC_HVM_CPUID (TRC_HVM_HANDLER + 0x0E)
+#define TRC_HVM_INTR (TRC_HVM_HANDLER + 0x0F)
+#define TRC_HVM_NMI (TRC_HVM_HANDLER + 0x10)
+#define TRC_HVM_SMI (TRC_HVM_HANDLER + 0x11)
+#define TRC_HVM_VMMCALL (TRC_HVM_HANDLER + 0x12)
+#define TRC_HVM_HLT (TRC_HVM_HANDLER + 0x13)
+#define TRC_HVM_INVLPG (TRC_HVM_HANDLER + 0x14)
+#define TRC_HVM_INVLPG64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x14)
+#define TRC_HVM_MCE (TRC_HVM_HANDLER + 0x15)
+#define TRC_HVM_IOPORT_READ (TRC_HVM_HANDLER + 0x16)
+#define TRC_HVM_IOMEM_READ (TRC_HVM_HANDLER + 0x17)
+#define TRC_HVM_CLTS (TRC_HVM_HANDLER + 0x18)
+#define TRC_HVM_LMSW (TRC_HVM_HANDLER + 0x19)
+#define TRC_HVM_LMSW64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x19)
+#define TRC_HVM_RDTSC (TRC_HVM_HANDLER + 0x1a)
+#define TRC_HVM_INTR_WINDOW (TRC_HVM_HANDLER + 0x20)
+#define TRC_HVM_NPF (TRC_HVM_HANDLER + 0x21)
+#define TRC_HVM_REALMODE_EMULATE (TRC_HVM_HANDLER + 0x22)
+#define TRC_HVM_TRAP (TRC_HVM_HANDLER + 0x23)
+#define TRC_HVM_TRAP_DEBUG (TRC_HVM_HANDLER + 0x24)
+#define TRC_HVM_VLAPIC (TRC_HVM_HANDLER + 0x25)
+
+#define TRC_HVM_IOPORT_WRITE (TRC_HVM_HANDLER + 0x216)
+#define TRC_HVM_IOMEM_WRITE (TRC_HVM_HANDLER + 0x217)
+
+/* Trace events for emulated devices */
+#define TRC_HVM_EMUL_HPET_START_TIMER (TRC_HVM_EMUL + 0x1)
+#define TRC_HVM_EMUL_PIT_START_TIMER (TRC_HVM_EMUL + 0x2)
+#define TRC_HVM_EMUL_RTC_START_TIMER (TRC_HVM_EMUL + 0x3)
+#define TRC_HVM_EMUL_LAPIC_START_TIMER (TRC_HVM_EMUL + 0x4)
+#define TRC_HVM_EMUL_HPET_STOP_TIMER (TRC_HVM_EMUL + 0x5)
+#define TRC_HVM_EMUL_PIT_STOP_TIMER (TRC_HVM_EMUL + 0x6)
+#define TRC_HVM_EMUL_RTC_STOP_TIMER (TRC_HVM_EMUL + 0x7)
+#define TRC_HVM_EMUL_LAPIC_STOP_TIMER (TRC_HVM_EMUL + 0x8)
+#define TRC_HVM_EMUL_PIT_TIMER_CB (TRC_HVM_EMUL + 0x9)
+#define TRC_HVM_EMUL_LAPIC_TIMER_CB (TRC_HVM_EMUL + 0xA)
+#define TRC_HVM_EMUL_PIC_INT_OUTPUT (TRC_HVM_EMUL + 0xB)
+#define TRC_HVM_EMUL_PIC_KICK (TRC_HVM_EMUL + 0xC)
+#define TRC_HVM_EMUL_PIC_INTACK (TRC_HVM_EMUL + 0xD)
+#define TRC_HVM_EMUL_PIC_POSEDGE (TRC_HVM_EMUL + 0xE)
+#define TRC_HVM_EMUL_PIC_NEGEDGE (TRC_HVM_EMUL + 0xF)
+#define TRC_HVM_EMUL_PIC_PEND_IRQ_CALL (TRC_HVM_EMUL + 0x10)
+#define TRC_HVM_EMUL_LAPIC_PIC_INTR (TRC_HVM_EMUL + 0x11)
+
+/* trace events for per class */
+#define TRC_PM_FREQ_CHANGE (TRC_HW_PM + 0x01)
+#define TRC_PM_IDLE_ENTRY (TRC_HW_PM + 0x02)
+#define TRC_PM_IDLE_EXIT (TRC_HW_PM + 0x03)
+
+/* Trace events for IRQs */
+#define TRC_HW_IRQ_MOVE_CLEANUP_DELAY (TRC_HW_IRQ + 0x1)
+#define TRC_HW_IRQ_MOVE_CLEANUP (TRC_HW_IRQ + 0x2)
+#define TRC_HW_IRQ_BIND_VECTOR (TRC_HW_IRQ + 0x3)
+#define TRC_HW_IRQ_CLEAR_VECTOR (TRC_HW_IRQ + 0x4)
+#define TRC_HW_IRQ_MOVE_FINISH (TRC_HW_IRQ + 0x5)
+#define TRC_HW_IRQ_ASSIGN_VECTOR (TRC_HW_IRQ + 0x6)
+#define TRC_HW_IRQ_UNMAPPED_VECTOR (TRC_HW_IRQ + 0x7)
+#define TRC_HW_IRQ_HANDLED (TRC_HW_IRQ + 0x8)
+
+/*
+ * Event Flags
+ *
+ * Some events (e.g, TRC_PV_TRAP and TRC_HVM_IOMEM_READ) have multiple
+ * record formats. These event flags distinguish between the
+ * different formats.
+ */
+#define TRC_64_FLAG 0x100 /* Addresses are 64 bits (instead of 32 bits) */
+
+/* This structure represents a single trace buffer record. */
+struct t_rec {
+ uint32_t event:28;
+ uint32_t extra_u32:3; /* # entries in trailing extra_u32[] array */
+ uint32_t cycles_included:1; /* u.cycles or u.no_cycles? */
+ union {
+ struct {
+ uint32_t cycles_lo, cycles_hi; /* cycle counter timestamp */
+ uint32_t extra_u32[7]; /* event data items */
+ } cycles;
+ struct {
+ uint32_t extra_u32[7]; /* event data items */
+ } nocycles;
+ } u;
+};
+
+/*
+ * This structure contains the metadata for a single trace buffer. The head
+ * field, indexes into an array of struct t_rec's.
+ */
+struct t_buf {
+ /* Assume the data buffer size is X. X is generally not a power of 2.
+ * CONS and PROD are incremented modulo (2*X):
+ * 0 <= cons < 2*X
+ * 0 <= prod < 2*X
+ * This is done because addition modulo X breaks at 2^32 when X is not a
+ * power of 2:
+ * (((2^32 - 1) % X) + 1) % X != (2^32) % X
+ */
+ uint32_t cons; /* Offset of next item to be consumed by control tools. */
+ uint32_t prod; /* Offset of next item to be produced by Xen. */
+ /* Records follow immediately after the meta-data header. */
+};
+
+/* Structure used to pass MFNs to the trace buffers back to trace consumers.
+ * Offset is an offset into the mapped structure where the mfn list will be held.
+ * MFNs will be at ((unsigned long *)(t_info))+(t_info->cpu_offset[cpu]).
+ */
+struct t_info {
+ uint16_t tbuf_size; /* Size in pages of each trace buffer */
+ uint16_t mfn_offset[]; /* Offset within t_info structure of the page list per cpu */
+ /* MFN lists immediately after the header */
+};
+
+#endif /* __XEN_PUBLIC_TRACE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * vcpu.h
+ *
+ * VCPU initialisation, query, and hotplug.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
+ */
+
+#ifndef __XEN_PUBLIC_VCPU_H__
+#define __XEN_PUBLIC_VCPU_H__
+
+#include "xen.h"
+
+/*
+ * Prototype for this hypercall is:
+ * long vcpu_op(int cmd, unsigned int vcpuid, void *extra_args)
+ * @cmd == VCPUOP_??? (VCPU operation).
+ * @vcpuid == VCPU to operate on.
+ * @extra_args == Operation-specific extra arguments (NULL if none).
+ */
+
+/*
+ * Initialise a VCPU. Each VCPU can be initialised only once. A
+ * newly-initialised VCPU will not run until it is brought up by VCPUOP_up.
+ *
+ * @extra_arg == pointer to vcpu_guest_context structure containing initial
+ * state for the VCPU.
+ */
+#define VCPUOP_initialise 0
+
+/*
+ * Bring up a VCPU. This makes the VCPU runnable. This operation will fail
+ * if the VCPU has not been initialised (VCPUOP_initialise).
+ */
+#define VCPUOP_up 1
+
+/*
+ * Bring down a VCPU (i.e., make it non-runnable).
+ * There are a few caveats that callers should observe:
+ * 1. This operation may return, and VCPU_is_up may return false, before the
+ * VCPU stops running (i.e., the command is asynchronous). It is a good
+ * idea to ensure that the VCPU has entered a non-critical loop before
+ * bringing it down. Alternatively, this operation is guaranteed
+ * synchronous if invoked by the VCPU itself.
+ * 2. After a VCPU is initialised, there is currently no way to drop all its
+ * references to domain memory. Even a VCPU that is down still holds
+ * memory references via its pagetable base pointer and GDT. It is good
+ * practise to move a VCPU onto an 'idle' or default page table, LDT and
+ * GDT before bringing it down.
+ */
+#define VCPUOP_down 2
+
+/* Returns 1 if the given VCPU is up. */
+#define VCPUOP_is_up 3
+
+/*
+ * Return information about the state and running time of a VCPU.
+ * @extra_arg == pointer to vcpu_runstate_info structure.
+ */
+#define VCPUOP_get_runstate_info 4
+struct vcpu_runstate_info {
+ /* VCPU's current state (RUNSTATE_*). */
+ int state;
+ /* When was current state entered (system time, ns)? */
+ uint64_t state_entry_time;
+ /*
+ * Time spent in each RUNSTATE_* (ns). The sum of these times is
+ * guaranteed not to drift from system time.
+ */
+ uint64_t time[4];
+};
+typedef struct vcpu_runstate_info vcpu_runstate_info_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_runstate_info_t);
+
+/* VCPU is currently running on a physical CPU. */
+#define RUNSTATE_running 0
+
+/* VCPU is runnable, but not currently scheduled on any physical CPU. */
+#define RUNSTATE_runnable 1
+
+/* VCPU is blocked (a.k.a. idle). It is therefore not runnable. */
+#define RUNSTATE_blocked 2
+
+/*
+ * VCPU is not runnable, but it is not blocked.
+ * This is a 'catch all' state for things like hotplug and pauses by the
+ * system administrator (or for critical sections in the hypervisor).
+ * RUNSTATE_blocked dominates this state (it is the preferred state).
+ */
+#define RUNSTATE_offline 3
+
+/*
+ * Register a shared memory area from which the guest may obtain its own
+ * runstate information without needing to execute a hypercall.
+ * Notes:
+ * 1. The registered address may be virtual or physical or guest handle,
+ * depending on the platform. Virtual address or guest handle should be
+ * registered on x86 systems.
+ * 2. Only one shared area may be registered per VCPU. The shared area is
+ * updated by the hypervisor each time the VCPU is scheduled. Thus
+ * runstate.state will always be RUNSTATE_running and
+ * runstate.state_entry_time will indicate the system time at which the
+ * VCPU was last scheduled to run.
+ * @extra_arg == pointer to vcpu_register_runstate_memory_area structure.
+ */
+#define VCPUOP_register_runstate_memory_area 5
+struct vcpu_register_runstate_memory_area {
+ union {
+ XEN_GUEST_HANDLE(vcpu_runstate_info_t) h;
+ struct vcpu_runstate_info *v;
+ uint64_t p;
+ } addr;
+};
+typedef struct vcpu_register_runstate_memory_area vcpu_register_runstate_memory_area_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_register_runstate_memory_area_t);
+
+/*
+ * Set or stop a VCPU's periodic timer. Every VCPU has one periodic timer
+ * which can be set via these commands. Periods smaller than one millisecond
+ * may not be supported.
+ */
+#define VCPUOP_set_periodic_timer 6 /* arg == vcpu_set_periodic_timer_t */
+#define VCPUOP_stop_periodic_timer 7 /* arg == NULL */
+struct vcpu_set_periodic_timer {
+ uint64_t period_ns;
+};
+typedef struct vcpu_set_periodic_timer vcpu_set_periodic_timer_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_set_periodic_timer_t);
+
+/*
+ * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot
+ * timer which can be set via these commands.
+ */
+#define VCPUOP_set_singleshot_timer 8 /* arg == vcpu_set_singleshot_timer_t */
+#define VCPUOP_stop_singleshot_timer 9 /* arg == NULL */
+struct vcpu_set_singleshot_timer {
+ uint64_t timeout_abs_ns; /* Absolute system time value in nanoseconds. */
+ uint32_t flags; /* VCPU_SSHOTTMR_??? */
+};
+typedef struct vcpu_set_singleshot_timer vcpu_set_singleshot_timer_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_set_singleshot_timer_t);
+
+/* Flags to VCPUOP_set_singleshot_timer. */
+ /* Require the timeout to be in the future (return -ETIME if it's passed). */
+#define _VCPU_SSHOTTMR_future (0)
+#define VCPU_SSHOTTMR_future (1U << _VCPU_SSHOTTMR_future)
+
+/*
+ * Register a memory location in the guest address space for the
+ * vcpu_info structure. This allows the guest to place the vcpu_info
+ * structure in a convenient place, such as in a per-cpu data area.
+ * The pointer need not be page aligned, but the structure must not
+ * cross a page boundary.
+ *
+ * This may be called only once per vcpu.
+ */
+#define VCPUOP_register_vcpu_info 10 /* arg == vcpu_register_vcpu_info_t */
+struct vcpu_register_vcpu_info {
+ uint64_t mfn; /* mfn of page to place vcpu_info */
+ uint32_t offset; /* offset within page */
+ uint32_t rsvd; /* unused */
+};
+typedef struct vcpu_register_vcpu_info vcpu_register_vcpu_info_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_register_vcpu_info_t);
+
+/* Send an NMI to the specified VCPU. @extra_arg == NULL. */
+#define VCPUOP_send_nmi 11
+
+/*
+ * Get the physical ID information for a pinned vcpu's underlying physical
+ * processor. The physical ID informmation is architecture-specific.
+ * On x86: id[31:0]=apic_id, id[63:32]=acpi_id.
+ * This command returns -EINVAL if it is not a valid operation for this VCPU.
+ */
+#define VCPUOP_get_physid 12 /* arg == vcpu_get_physid_t */
+struct vcpu_get_physid {
+ uint64_t phys_id;
+};
+typedef struct vcpu_get_physid vcpu_get_physid_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_get_physid_t);
+#define xen_vcpu_physid_to_x86_apicid(physid) ((uint32_t)(physid))
+#define xen_vcpu_physid_to_x86_acpiid(physid) ((uint32_t)((physid) >> 32))
+
+/*
+ * Register a memory location to get a secondary copy of the vcpu time
+ * parameters. The master copy still exists as part of the vcpu shared
+ * memory area, and this secondary copy is updated whenever the master copy
+ * is updated (and using the same versioning scheme for synchronisation).
+ *
+ * The intent is that this copy may be mapped (RO) into userspace so
+ * that usermode can compute system time using the time info and the
+ * tsc. Usermode will see an array of vcpu_time_info structures, one
+ * for each vcpu, and choose the right one by an existing mechanism
+ * which allows it to get the current vcpu number (such as via a
+ * segment limit). It can then apply the normal algorithm to compute
+ * system time from the tsc.
+ *
+ * @extra_arg == pointer to vcpu_register_time_info_memory_area structure.
+ */
+#define VCPUOP_register_vcpu_time_memory_area 13
+DEFINE_XEN_GUEST_HANDLE(vcpu_time_info_t);
+struct vcpu_register_time_memory_area {
+ union {
+ XEN_GUEST_HANDLE(vcpu_time_info_t) h;
+ struct vcpu_time_info *v;
+ uint64_t p;
+ } addr;
+};
+typedef struct vcpu_register_time_memory_area vcpu_register_time_memory_area_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_register_time_memory_area_t);
+
+#endif /* __XEN_PUBLIC_VCPU_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * version.h
+ *
+ * Xen version, type, and compile information.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2005, Nguyen Anh Quynh <aquynh@gmail.com>
+ * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
+ */
+
+#ifndef __XEN_PUBLIC_VERSION_H__
+#define __XEN_PUBLIC_VERSION_H__
+
+#include "xen.h"
+
+/* NB. All ops return zero on success, except XENVER_{version,pagesize} */
+
+/* arg == NULL; returns major:minor (16:16). */
+#define XENVER_version 0
+
+/* arg == xen_extraversion_t. */
+#define XENVER_extraversion 1
+typedef char xen_extraversion_t[16];
+#define XEN_EXTRAVERSION_LEN (sizeof(xen_extraversion_t))
+
+/* arg == xen_compile_info_t. */
+#define XENVER_compile_info 2
+struct xen_compile_info {
+ char compiler[64];
+ char compile_by[16];
+ char compile_domain[32];
+ char compile_date[32];
+};
+typedef struct xen_compile_info xen_compile_info_t;
+
+#define XENVER_capabilities 3
+typedef char xen_capabilities_info_t[1024];
+#define XEN_CAPABILITIES_INFO_LEN (sizeof(xen_capabilities_info_t))
+
+#define XENVER_changeset 4
+typedef char xen_changeset_info_t[64];
+#define XEN_CHANGESET_INFO_LEN (sizeof(xen_changeset_info_t))
+
+#define XENVER_platform_parameters 5
+struct xen_platform_parameters {
+ xen_ulong_t virt_start;
+};
+typedef struct xen_platform_parameters xen_platform_parameters_t;
+
+#define XENVER_get_features 6
+struct xen_feature_info {
+ unsigned int submap_idx; /* IN: which 32-bit submap to return */
+ uint32_t submap; /* OUT: 32-bit submap */
+};
+typedef struct xen_feature_info xen_feature_info_t;
+
+/* Declares the features reported by XENVER_get_features. */
+#include "features.h"
+
+/* arg == NULL; returns host memory page size. */
+#define XENVER_pagesize 7
+
+/* arg == xen_domain_handle_t. */
+#define XENVER_guest_handle 8
+
+#define XENVER_commandline 9
+typedef char xen_commandline_t[1024];
+
+#endif /* __XEN_PUBLIC_VERSION_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * xen-compat.h
+ *
+ * Guest OS interface to Xen. Compatibility layer.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2006, Christian Limpach
+ */
+
+#ifndef __XEN_PUBLIC_XEN_COMPAT_H__
+#define __XEN_PUBLIC_XEN_COMPAT_H__
+
+#define __XEN_LATEST_INTERFACE_VERSION__ 0x00040600
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+/* Xen is built with matching headers and implements the latest interface. */
+#define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__
+#elif !defined(__XEN_INTERFACE_VERSION__)
+/* Guests which do not specify a version get the legacy interface. */
+#define __XEN_INTERFACE_VERSION__ 0x00000000
+#endif
+
+#if __XEN_INTERFACE_VERSION__ > __XEN_LATEST_INTERFACE_VERSION__
+#error "These header files do not support the requested interface version."
+#endif
+
+#endif /* __XEN_PUBLIC_XEN_COMPAT_H__ */
--- /dev/null
+/******************************************************************************
+ * xen.h
+ *
+ * Guest OS interface to Xen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#ifndef __XEN_PUBLIC_XEN_H__
+#define __XEN_PUBLIC_XEN_H__
+
+#include "xen-compat.h"
+
+#if defined(__i386__) || defined(__x86_64__)
+#include "arch-x86/xen.h"
+#elif defined(__arm__) || defined (__aarch64__)
+#include "arch-arm.h"
+#else
+#error "Unsupported architecture"
+#endif
+
+#ifndef __ASSEMBLY__
+/* Guest handles for primitive C types. */
+DEFINE_XEN_GUEST_HANDLE(char);
+__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
+DEFINE_XEN_GUEST_HANDLE(int);
+__DEFINE_XEN_GUEST_HANDLE(uint, unsigned int);
+#if __XEN_INTERFACE_VERSION__ < 0x00040300
+DEFINE_XEN_GUEST_HANDLE(long);
+__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
+#endif
+DEFINE_XEN_GUEST_HANDLE(void);
+
+DEFINE_XEN_GUEST_HANDLE(uint64_t);
+DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
+DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
+#endif
+
+/*
+ * HYPERCALLS
+ */
+
+/* `incontents 100 hcalls List of hypercalls
+ * ` enum hypercall_num { // __HYPERVISOR_* => HYPERVISOR_*()
+ */
+
+#define __HYPERVISOR_set_trap_table 0
+#define __HYPERVISOR_mmu_update 1
+#define __HYPERVISOR_set_gdt 2
+#define __HYPERVISOR_stack_switch 3
+#define __HYPERVISOR_set_callbacks 4
+#define __HYPERVISOR_fpu_taskswitch 5
+#define __HYPERVISOR_sched_op_compat 6 /* compat since 0x00030101 */
+#define __HYPERVISOR_platform_op 7
+#define __HYPERVISOR_set_debugreg 8
+#define __HYPERVISOR_get_debugreg 9
+#define __HYPERVISOR_update_descriptor 10
+#define __HYPERVISOR_memory_op 12
+#define __HYPERVISOR_multicall 13
+#define __HYPERVISOR_update_va_mapping 14
+#define __HYPERVISOR_set_timer_op 15
+#define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */
+#define __HYPERVISOR_xen_version 17
+#define __HYPERVISOR_console_io 18
+#define __HYPERVISOR_physdev_op_compat 19 /* compat since 0x00030202 */
+#define __HYPERVISOR_grant_table_op 20
+#define __HYPERVISOR_vm_assist 21
+#define __HYPERVISOR_update_va_mapping_otherdomain 22
+#define __HYPERVISOR_iret 23 /* x86 only */
+#define __HYPERVISOR_vcpu_op 24
+#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */
+#define __HYPERVISOR_mmuext_op 26
+#define __HYPERVISOR_xsm_op 27
+#define __HYPERVISOR_nmi_op 28
+#define __HYPERVISOR_sched_op 29
+#define __HYPERVISOR_callback_op 30
+#define __HYPERVISOR_xenoprof_op 31
+#define __HYPERVISOR_event_channel_op 32
+#define __HYPERVISOR_physdev_op 33
+#define __HYPERVISOR_hvm_op 34
+#define __HYPERVISOR_sysctl 35
+#define __HYPERVISOR_domctl 36
+#define __HYPERVISOR_kexec_op 37
+#define __HYPERVISOR_tmem_op 38
+#define __HYPERVISOR_xc_reserved_op 39 /* reserved for XenClient */
+
+/* Architecture-specific hypercall definitions. */
+#define __HYPERVISOR_arch_0 48
+#define __HYPERVISOR_arch_1 49
+#define __HYPERVISOR_arch_2 50
+#define __HYPERVISOR_arch_3 51
+#define __HYPERVISOR_arch_4 52
+#define __HYPERVISOR_arch_5 53
+#define __HYPERVISOR_arch_6 54
+#define __HYPERVISOR_arch_7 55
+
+/* ` } */
+
+/*
+ * HYPERCALL COMPATIBILITY.
+ */
+
+/* New sched_op hypercall introduced in 0x00030101. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030101
+#undef __HYPERVISOR_sched_op
+#define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat
+#endif
+
+/* New event-channel and physdev hypercalls introduced in 0x00030202. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030202
+#undef __HYPERVISOR_event_channel_op
+#define __HYPERVISOR_event_channel_op __HYPERVISOR_event_channel_op_compat
+#undef __HYPERVISOR_physdev_op
+#define __HYPERVISOR_physdev_op __HYPERVISOR_physdev_op_compat
+#endif
+
+/* New platform_op hypercall introduced in 0x00030204. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030204
+#define __HYPERVISOR_dom0_op __HYPERVISOR_platform_op
+#endif
+
+/*
+ * VIRTUAL INTERRUPTS
+ *
+ * Virtual interrupts that a guest OS may receive from Xen.
+ *
+ * In the side comments, 'V.' denotes a per-VCPU VIRQ while 'G.' denotes a
+ * global VIRQ. The former can be bound once per VCPU and cannot be re-bound.
+ * The latter can be allocated only once per guest: they must initially be
+ * allocated to VCPU0 but can subsequently be re-bound.
+ */
+/* ` enum virq { */
+#define VIRQ_TIMER 0 /* V. Timebase update, and/or requested timeout. */
+#define VIRQ_DEBUG 1 /* V. Request guest to dump debug info. */
+#define VIRQ_CONSOLE 2 /* G. (DOM0) Bytes received on emergency console. */
+#define VIRQ_DOM_EXC 3 /* G. (DOM0) Exceptional event for some domain. */
+#define VIRQ_TBUF 4 /* G. (DOM0) Trace buffer has records available. */
+#define VIRQ_DEBUGGER 6 /* G. (DOM0) A domain has paused for debugging. */
+#define VIRQ_XENOPROF 7 /* V. XenOprofile interrupt: new sample available */
+#define VIRQ_CON_RING 8 /* G. (DOM0) Bytes received on console */
+#define VIRQ_PCPU_STATE 9 /* G. (DOM0) PCPU state changed */
+#define VIRQ_MEM_EVENT 10 /* G. (DOM0) A memory event has occured */
+#define VIRQ_XC_RESERVED 11 /* G. Reserved for XenClient */
+#define VIRQ_ENOMEM 12 /* G. (DOM0) Low on heap memory */
+
+/* Architecture-specific VIRQ definitions. */
+#define VIRQ_ARCH_0 16
+#define VIRQ_ARCH_1 17
+#define VIRQ_ARCH_2 18
+#define VIRQ_ARCH_3 19
+#define VIRQ_ARCH_4 20
+#define VIRQ_ARCH_5 21
+#define VIRQ_ARCH_6 22
+#define VIRQ_ARCH_7 23
+/* ` } */
+
+#define NR_VIRQS 24
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_mmu_update(const struct mmu_update reqs[],
+ * ` unsigned count, unsigned *done_out,
+ * ` unsigned foreigndom)
+ * `
+ * @reqs is an array of mmu_update_t structures ((ptr, val) pairs).
+ * @count is the length of the above array.
+ * @pdone is an output parameter indicating number of completed operations
+ * @foreigndom[15:0]: FD, the expected owner of data pages referenced in this
+ * hypercall invocation. Can be DOMID_SELF.
+ * @foreigndom[31:16]: PFD, the expected owner of pagetable pages referenced
+ * in this hypercall invocation. The value of this field
+ * (x) encodes the PFD as follows:
+ * x == 0 => PFD == DOMID_SELF
+ * x != 0 => PFD == x - 1
+ *
+ * Sub-commands: ptr[1:0] specifies the appropriate MMU_* command.
+ * -------------
+ * ptr[1:0] == MMU_NORMAL_PT_UPDATE:
+ * Updates an entry in a page table belonging to PFD. If updating an L1 table,
+ * and the new table entry is valid/present, the mapped frame must belong to
+ * FD. If attempting to map an I/O page then the caller assumes the privilege
+ * of the FD.
+ * FD == DOMID_IO: Permit /only/ I/O mappings, at the priv level of the caller.
+ * FD == DOMID_XEN: Map restricted areas of Xen's heap space.
+ * ptr[:2] -- Machine address of the page-table entry to modify.
+ * val -- Value to write.
+ *
+ * There also certain implicit requirements when using this hypercall. The
+ * pages that make up a pagetable must be mapped read-only in the guest.
+ * This prevents uncontrolled guest updates to the pagetable. Xen strictly
+ * enforces this, and will disallow any pagetable update which will end up
+ * mapping pagetable page RW, and will disallow using any writable page as a
+ * pagetable. In practice it means that when constructing a page table for a
+ * process, thread, etc, we MUST be very dilligient in following these rules:
+ * 1). Start with top-level page (PGD or in Xen language: L4). Fill out
+ * the entries.
+ * 2). Keep on going, filling out the upper (PUD or L3), and middle (PMD
+ * or L2).
+ * 3). Start filling out the PTE table (L1) with the PTE entries. Once
+ * done, make sure to set each of those entries to RO (so writeable bit
+ * is unset). Once that has been completed, set the PMD (L2) for this
+ * PTE table as RO.
+ * 4). When completed with all of the PMD (L2) entries, and all of them have
+ * been set to RO, make sure to set RO the PUD (L3). Do the same
+ * operation on PGD (L4) pagetable entries that have a PUD (L3) entry.
+ * 5). Now before you can use those pages (so setting the cr3), you MUST also
+ * pin them so that the hypervisor can verify the entries. This is done
+ * via the HYPERVISOR_mmuext_op(MMUEXT_PIN_L4_TABLE, guest physical frame
+ * number of the PGD (L4)). And this point the HYPERVISOR_mmuext_op(
+ * MMUEXT_NEW_BASEPTR, guest physical frame number of the PGD (L4)) can be
+ * issued.
+ * For 32-bit guests, the L4 is not used (as there is less pagetables), so
+ * instead use L3.
+ * At this point the pagetables can be modified using the MMU_NORMAL_PT_UPDATE
+ * hypercall. Also if so desired the OS can also try to write to the PTE
+ * and be trapped by the hypervisor (as the PTE entry is RO).
+ *
+ * To deallocate the pages, the operations are the reverse of the steps
+ * mentioned above. The argument is MMUEXT_UNPIN_TABLE for all levels and the
+ * pagetable MUST not be in use (meaning that the cr3 is not set to it).
+ *
+ * ptr[1:0] == MMU_MACHPHYS_UPDATE:
+ * Updates an entry in the machine->pseudo-physical mapping table.
+ * ptr[:2] -- Machine address within the frame whose mapping to modify.
+ * The frame must belong to the FD, if one is specified.
+ * val -- Value to write into the mapping entry.
+ *
+ * ptr[1:0] == MMU_PT_UPDATE_PRESERVE_AD:
+ * As MMU_NORMAL_PT_UPDATE above, but A/D bits currently in the PTE are ORed
+ * with those in @val.
+ *
+ * @val is usually the machine frame number along with some attributes.
+ * The attributes by default follow the architecture defined bits. Meaning that
+ * if this is a X86_64 machine and four page table layout is used, the layout
+ * of val is:
+ * - 63 if set means No execute (NX)
+ * - 46-13 the machine frame number
+ * - 12 available for guest
+ * - 11 available for guest
+ * - 10 available for guest
+ * - 9 available for guest
+ * - 8 global
+ * - 7 PAT (PSE is disabled, must use hypercall to make 4MB or 2MB pages)
+ * - 6 dirty
+ * - 5 accessed
+ * - 4 page cached disabled
+ * - 3 page write through
+ * - 2 userspace accessible
+ * - 1 writeable
+ * - 0 present
+ *
+ * The one bits that does not fit with the default layout is the PAGE_PSE
+ * also called PAGE_PAT). The MMUEXT_[UN]MARK_SUPER arguments to the
+ * HYPERVISOR_mmuext_op serve as mechanism to set a pagetable to be 4MB
+ * (or 2MB) instead of using the PAGE_PSE bit.
+ *
+ * The reason that the PAGE_PSE (bit 7) is not being utilized is due to Xen
+ * using it as the Page Attribute Table (PAT) bit - for details on it please
+ * refer to Intel SDM 10.12. The PAT allows to set the caching attributes of
+ * pages instead of using MTRRs.
+ *
+ * The PAT MSR is as follows (it is a 64-bit value, each entry is 8 bits):
+ * PAT4 PAT0
+ * +-----+-----+----+----+----+-----+----+----+
+ * | UC | UC- | WC | WB | UC | UC- | WC | WB | <= Linux
+ * +-----+-----+----+----+----+-----+----+----+
+ * | UC | UC- | WT | WB | UC | UC- | WT | WB | <= BIOS (default when machine boots)
+ * +-----+-----+----+----+----+-----+----+----+
+ * | rsv | rsv | WP | WC | UC | UC- | WT | WB | <= Xen
+ * +-----+-----+----+----+----+-----+----+----+
+ *
+ * The lookup of this index table translates to looking up
+ * Bit 7, Bit 4, and Bit 3 of val entry:
+ *
+ * PAT/PSE (bit 7) ... PCD (bit 4) .. PWT (bit 3).
+ *
+ * If all bits are off, then we are using PAT0. If bit 3 turned on,
+ * then we are using PAT1, if bit 3 and bit 4, then PAT2..
+ *
+ * As you can see, the Linux PAT1 translates to PAT4 under Xen. Which means
+ * that if a guest that follows Linux's PAT setup and would like to set Write
+ * Combined on pages it MUST use PAT4 entry. Meaning that Bit 7 (PAGE_PAT) is
+ * set. For example, under Linux it only uses PAT0, PAT1, and PAT2 for the
+ * caching as:
+ *
+ * WB = none (so PAT0)
+ * WC = PWT (bit 3 on)
+ * UC = PWT | PCD (bit 3 and 4 are on).
+ *
+ * To make it work with Xen, it needs to translate the WC bit as so:
+ *
+ * PWT (so bit 3 on) --> PAT (so bit 7 is on) and clear bit 3
+ *
+ * And to translate back it would:
+ *
+ * PAT (bit 7 on) --> PWT (bit 3 on) and clear bit 7.
+ */
+#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */
+#define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */
+#define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */
+
+/*
+ * MMU EXTENDED OPERATIONS
+ *
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_mmuext_op(mmuext_op_t uops[],
+ * ` unsigned int count,
+ * ` unsigned int *pdone,
+ * ` unsigned int foreigndom)
+ */
+/* HYPERVISOR_mmuext_op() accepts a list of mmuext_op structures.
+ * A foreigndom (FD) can be specified (or DOMID_SELF for none).
+ * Where the FD has some effect, it is described below.
+ *
+ * cmd: MMUEXT_(UN)PIN_*_TABLE
+ * mfn: Machine frame number to be (un)pinned as a p.t. page.
+ * The frame must belong to the FD, if one is specified.
+ *
+ * cmd: MMUEXT_NEW_BASEPTR
+ * mfn: Machine frame number of new page-table base to install in MMU.
+ *
+ * cmd: MMUEXT_NEW_USER_BASEPTR [x86/64 only]
+ * mfn: Machine frame number of new page-table base to install in MMU
+ * when in user space.
+ *
+ * cmd: MMUEXT_TLB_FLUSH_LOCAL
+ * No additional arguments. Flushes local TLB.
+ *
+ * cmd: MMUEXT_INVLPG_LOCAL
+ * linear_addr: Linear address to be flushed from the local TLB.
+ *
+ * cmd: MMUEXT_TLB_FLUSH_MULTI
+ * vcpumask: Pointer to bitmap of VCPUs to be flushed.
+ *
+ * cmd: MMUEXT_INVLPG_MULTI
+ * linear_addr: Linear address to be flushed.
+ * vcpumask: Pointer to bitmap of VCPUs to be flushed.
+ *
+ * cmd: MMUEXT_TLB_FLUSH_ALL
+ * No additional arguments. Flushes all VCPUs' TLBs.
+ *
+ * cmd: MMUEXT_INVLPG_ALL
+ * linear_addr: Linear address to be flushed from all VCPUs' TLBs.
+ *
+ * cmd: MMUEXT_FLUSH_CACHE
+ * No additional arguments. Writes back and flushes cache contents.
+ *
+ * cmd: MMUEXT_FLUSH_CACHE_GLOBAL
+ * No additional arguments. Writes back and flushes cache contents
+ * on all CPUs in the system.
+ *
+ * cmd: MMUEXT_SET_LDT
+ * linear_addr: Linear address of LDT base (NB. must be page-aligned).
+ * nr_ents: Number of entries in LDT.
+ *
+ * cmd: MMUEXT_CLEAR_PAGE
+ * mfn: Machine frame number to be cleared.
+ *
+ * cmd: MMUEXT_COPY_PAGE
+ * mfn: Machine frame number of the destination page.
+ * src_mfn: Machine frame number of the source page.
+ *
+ * cmd: MMUEXT_[UN]MARK_SUPER
+ * mfn: Machine frame number of head of superpage to be [un]marked.
+ */
+/* ` enum mmuext_cmd { */
+#define MMUEXT_PIN_L1_TABLE 0
+#define MMUEXT_PIN_L2_TABLE 1
+#define MMUEXT_PIN_L3_TABLE 2
+#define MMUEXT_PIN_L4_TABLE 3
+#define MMUEXT_UNPIN_TABLE 4
+#define MMUEXT_NEW_BASEPTR 5
+#define MMUEXT_TLB_FLUSH_LOCAL 6
+#define MMUEXT_INVLPG_LOCAL 7
+#define MMUEXT_TLB_FLUSH_MULTI 8
+#define MMUEXT_INVLPG_MULTI 9
+#define MMUEXT_TLB_FLUSH_ALL 10
+#define MMUEXT_INVLPG_ALL 11
+#define MMUEXT_FLUSH_CACHE 12
+#define MMUEXT_SET_LDT 13
+#define MMUEXT_NEW_USER_BASEPTR 15
+#define MMUEXT_CLEAR_PAGE 16
+#define MMUEXT_COPY_PAGE 17
+#define MMUEXT_FLUSH_CACHE_GLOBAL 18
+#define MMUEXT_MARK_SUPER 19
+#define MMUEXT_UNMARK_SUPER 20
+/* ` } */
+
+#ifndef __ASSEMBLY__
+struct mmuext_op {
+ unsigned int cmd; /* => enum mmuext_cmd */
+ union {
+ /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR
+ * CLEAR_PAGE, COPY_PAGE, [UN]MARK_SUPER */
+ xen_pfn_t mfn;
+ /* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */
+ unsigned long linear_addr;
+ } arg1;
+ union {
+ /* SET_LDT */
+ unsigned int nr_ents;
+ /* TLB_FLUSH_MULTI, INVLPG_MULTI */
+#if __XEN_INTERFACE_VERSION__ >= 0x00030205
+ XEN_GUEST_HANDLE(const_void) vcpumask;
+#else
+ const void *vcpumask;
+#endif
+ /* COPY_PAGE */
+ xen_pfn_t src_mfn;
+ } arg2;
+};
+typedef struct mmuext_op mmuext_op_t;
+DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
+#endif
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_update_va_mapping(unsigned long va, u64 val,
+ * ` enum uvm_flags flags)
+ * `
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, u64 val,
+ * ` enum uvm_flags flags,
+ * ` domid_t domid)
+ * `
+ * ` @va: The virtual address whose mapping we want to change
+ * ` @val: The new page table entry, must contain a machine address
+ * ` @flags: Control TLB flushes
+ */
+/* These are passed as 'flags' to update_va_mapping. They can be ORed. */
+/* When specifying UVMF_MULTI, also OR in a pointer to a CPU bitmap. */
+/* UVMF_LOCAL is merely UVMF_MULTI with a NULL bitmap pointer. */
+/* ` enum uvm_flags { */
+#define UVMF_NONE (0UL<<0) /* No flushing at all. */
+#define UVMF_TLB_FLUSH (1UL<<0) /* Flush entire TLB(s). */
+#define UVMF_INVLPG (2UL<<0) /* Flush only one entry. */
+#define UVMF_FLUSHTYPE_MASK (3UL<<0)
+#define UVMF_MULTI (0UL<<2) /* Flush subset of TLBs. */
+#define UVMF_LOCAL (0UL<<2) /* Flush local TLB. */
+#define UVMF_ALL (1UL<<2) /* Flush all TLBs. */
+/* ` } */
+
+/*
+ * Commands to HYPERVISOR_console_io().
+ */
+#define CONSOLEIO_write 0
+#define CONSOLEIO_read 1
+
+/*
+ * Commands to HYPERVISOR_vm_assist().
+ */
+#define VMASST_CMD_enable 0
+#define VMASST_CMD_disable 1
+
+/* x86/32 guests: simulate full 4GB segment limits. */
+#define VMASST_TYPE_4gb_segments 0
+
+/* x86/32 guests: trap (vector 15) whenever above vmassist is used. */
+#define VMASST_TYPE_4gb_segments_notify 1
+
+/*
+ * x86 guests: support writes to bottom-level PTEs.
+ * NB1. Page-directory entries cannot be written.
+ * NB2. Guest must continue to remove all writable mappings of PTEs.
+ */
+#define VMASST_TYPE_writable_pagetables 2
+
+/* x86/PAE guests: support PDPTs above 4GB. */
+#define VMASST_TYPE_pae_extended_cr3 3
+
+#define MAX_VMASST_TYPE 3
+
+#ifndef __ASSEMBLY__
+
+typedef uint16_t domid_t;
+
+/* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary domains. */
+#define DOMID_FIRST_RESERVED (0x7FF0U)
+
+/* DOMID_SELF is used in certain contexts to refer to oneself. */
+#define DOMID_SELF (0x7FF0U)
+
+/*
+ * DOMID_IO is used to restrict page-table updates to mapping I/O memory.
+ * Although no Foreign Domain need be specified to map I/O pages, DOMID_IO
+ * is useful to ensure that no mappings to the OS's own heap are accidentally
+ * installed. (e.g., in Linux this could cause havoc as reference counts
+ * aren't adjusted on the I/O-mapping code path).
+ * This only makes sense in MMUEXT_SET_FOREIGNDOM, but in that context can
+ * be specified by any calling domain.
+ */
+#define DOMID_IO (0x7FF1U)
+
+/*
+ * DOMID_XEN is used to allow privileged domains to map restricted parts of
+ * Xen's heap space (e.g., the machine_to_phys table).
+ * This only makes sense in MMUEXT_SET_FOREIGNDOM, and is only permitted if
+ * the caller is privileged.
+ */
+#define DOMID_XEN (0x7FF2U)
+
+/*
+ * DOMID_COW is used as the owner of sharable pages */
+#define DOMID_COW (0x7FF3U)
+
+/* DOMID_INVALID is used to identify pages with unknown owner. */
+#define DOMID_INVALID (0x7FF4U)
+
+/* Idle domain. */
+#define DOMID_IDLE (0x7FFFU)
+
+/*
+ * Send an array of these to HYPERVISOR_mmu_update().
+ * NB. The fields are natural pointer/address size for this architecture.
+ */
+struct mmu_update {
+ uint64_t ptr; /* Machine address of PTE. */
+ uint64_t val; /* New contents of PTE. */
+};
+typedef struct mmu_update mmu_update_t;
+DEFINE_XEN_GUEST_HANDLE(mmu_update_t);
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_multicall(multicall_entry_t call_list[],
+ * ` uint32_t nr_calls);
+ *
+ * NB. The fields are logically the natural register size for this
+ * architecture. In cases where xen_ulong_t is larger than this then
+ * any unused bits in the upper portion must be zero.
+ */
+struct multicall_entry {
+ xen_ulong_t op, result;
+ xen_ulong_t args[6];
+};
+typedef struct multicall_entry multicall_entry_t;
+DEFINE_XEN_GUEST_HANDLE(multicall_entry_t);
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040400
+/*
+ * Event channel endpoints per domain (when using the 2-level ABI):
+ * 1024 if a long is 32 bits; 4096 if a long is 64 bits.
+ */
+#define NR_EVENT_CHANNELS EVTCHN_2L_NR_CHANNELS
+#endif
+
+struct vcpu_time_info {
+ /*
+ * Updates to the following values are preceded and followed by an
+ * increment of 'version'. The guest can therefore detect updates by
+ * looking for changes to 'version'. If the least-significant bit of
+ * the version number is set then an update is in progress and the guest
+ * must wait to read a consistent set of values.
+ * The correct way to interact with the version number is similar to
+ * Linux's seqlock: see the implementations of read_seqbegin/read_seqretry.
+ */
+ uint32_t version;
+ uint32_t pad0;
+ uint64_t tsc_timestamp; /* TSC at last update of time vals. */
+ uint64_t system_time; /* Time, in nanosecs, since boot. */
+ /*
+ * Current system time:
+ * system_time +
+ * ((((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul) >> 32)
+ * CPU frequency (Hz):
+ * ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift
+ */
+ uint32_t tsc_to_system_mul;
+ int8_t tsc_shift;
+ int8_t pad1[3];
+}; /* 32 bytes */
+typedef struct vcpu_time_info vcpu_time_info_t;
+
+struct vcpu_info {
+ /*
+ * 'evtchn_upcall_pending' is written non-zero by Xen to indicate
+ * a pending notification for a particular VCPU. It is then cleared
+ * by the guest OS /before/ checking for pending work, thus avoiding
+ * a set-and-check race. Note that the mask is only accessed by Xen
+ * on the CPU that is currently hosting the VCPU. This means that the
+ * pending and mask flags can be updated by the guest without special
+ * synchronisation (i.e., no need for the x86 LOCK prefix).
+ * This may seem suboptimal because if the pending flag is set by
+ * a different CPU then an IPI may be scheduled even when the mask
+ * is set. However, note:
+ * 1. The task of 'interrupt holdoff' is covered by the per-event-
+ * channel mask bits. A 'noisy' event that is continually being
+ * triggered can be masked at source at this very precise
+ * granularity.
+ * 2. The main purpose of the per-VCPU mask is therefore to restrict
+ * reentrant execution: whether for concurrency control, or to
+ * prevent unbounded stack usage. Whatever the purpose, we expect
+ * that the mask will be asserted only for short periods at a time,
+ * and so the likelihood of a 'spurious' IPI is suitably small.
+ * The mask is read before making an event upcall to the guest: a
+ * non-zero mask therefore guarantees that the VCPU will not receive
+ * an upcall activation. The mask is cleared when the VCPU requests
+ * to block: this avoids wakeup-waiting races.
+ */
+ uint8_t evtchn_upcall_pending;
+#ifdef XEN_HAVE_PV_UPCALL_MASK
+ uint8_t evtchn_upcall_mask;
+#else /* XEN_HAVE_PV_UPCALL_MASK */
+ uint8_t pad0;
+#endif /* XEN_HAVE_PV_UPCALL_MASK */
+ xen_ulong_t evtchn_pending_sel;
+ struct arch_vcpu_info arch;
+ struct vcpu_time_info time;
+}; /* 64 bytes (x86) */
+#ifndef __XEN__
+typedef struct vcpu_info vcpu_info_t;
+#endif
+
+/*
+ * `incontents 200 startofday_shared Start-of-day shared data structure
+ * Xen/kernel shared data -- pointer provided in start_info.
+ *
+ * This structure is defined to be both smaller than a page, and the
+ * only data on the shared page, but may vary in actual size even within
+ * compatible Xen versions; guests should not rely on the size
+ * of this structure remaining constant.
+ */
+struct shared_info {
+ struct vcpu_info vcpu_info[XEN_LEGACY_MAX_VCPUS];
+
+ /*
+ * A domain can create "event channels" on which it can send and receive
+ * asynchronous event notifications. There are three classes of event that
+ * are delivered by this mechanism:
+ * 1. Bi-directional inter- and intra-domain connections. Domains must
+ * arrange out-of-band to set up a connection (usually by allocating
+ * an unbound 'listener' port and avertising that via a storage service
+ * such as xenstore).
+ * 2. Physical interrupts. A domain with suitable hardware-access
+ * privileges can bind an event-channel port to a physical interrupt
+ * source.
+ * 3. Virtual interrupts ('events'). A domain can bind an event-channel
+ * port to a virtual interrupt source, such as the virtual-timer
+ * device or the emergency console.
+ *
+ * Event channels are addressed by a "port index". Each channel is
+ * associated with two bits of information:
+ * 1. PENDING -- notifies the domain that there is a pending notification
+ * to be processed. This bit is cleared by the guest.
+ * 2. MASK -- if this bit is clear then a 0->1 transition of PENDING
+ * will cause an asynchronous upcall to be scheduled. This bit is only
+ * updated by the guest. It is read-only within Xen. If a channel
+ * becomes pending while the channel is masked then the 'edge' is lost
+ * (i.e., when the channel is unmasked, the guest must manually handle
+ * pending notifications as no upcall will be scheduled by Xen).
+ *
+ * To expedite scanning of pending notifications, any 0->1 pending
+ * transition on an unmasked channel causes a corresponding bit in a
+ * per-vcpu selector word to be set. Each bit in the selector covers a
+ * 'C long' in the PENDING bitfield array.
+ */
+ xen_ulong_t evtchn_pending[sizeof(xen_ulong_t) * 8];
+ xen_ulong_t evtchn_mask[sizeof(xen_ulong_t) * 8];
+
+ /*
+ * Wallclock time: updated only by control software. Guests should base
+ * their gettimeofday() syscall on this wallclock-base value.
+ */
+ uint32_t wc_version; /* Version counter: see vcpu_time_info_t. */
+ uint32_t wc_sec; /* Secs 00:00:00 UTC, Jan 1, 1970. */
+ uint32_t wc_nsec; /* Nsecs 00:00:00 UTC, Jan 1, 1970. */
+
+ struct arch_shared_info arch;
+
+};
+#ifndef __XEN__
+typedef struct shared_info shared_info_t;
+#endif
+
+/*
+ * `incontents 200 startofday Start-of-day memory layout
+ *
+ * 1. The domain is started within contiguous virtual-memory region.
+ * 2. The contiguous region ends on an aligned 4MB boundary.
+ * 3. This the order of bootstrap elements in the initial virtual region:
+ * a. relocated kernel image
+ * b. initial ram disk [mod_start, mod_len]
+ * c. list of allocated page frames [mfn_list, nr_pages]
+ * (unless relocated due to XEN_ELFNOTE_INIT_P2M)
+ * d. start_info_t structure [register ESI (x86)]
+ * e. bootstrap page tables [pt_base and CR3 (x86)]
+ * f. bootstrap stack [register ESP (x86)]
+ * 4. Bootstrap elements are packed together, but each is 4kB-aligned.
+ * 5. The initial ram disk may be omitted.
+ * 6. The list of page frames forms a contiguous 'pseudo-physical' memory
+ * layout for the domain. In particular, the bootstrap virtual-memory
+ * region is a 1:1 mapping to the first section of the pseudo-physical map.
+ * 7. All bootstrap elements are mapped read-writable for the guest OS. The
+ * only exception is the bootstrap page table, which is mapped read-only.
+ * 8. There is guaranteed to be at least 512kB padding after the final
+ * bootstrap element. If necessary, the bootstrap virtual region is
+ * extended by an extra 4MB to ensure this.
+ *
+ * Note: Prior to 25833:bb85bbccb1c9. ("x86/32-on-64 adjust Dom0 initial page
+ * table layout") a bug caused the pt_base (3.e above) and cr3 to not point
+ * to the start of the guest page tables (it was offset by two pages).
+ * This only manifested itself on 32-on-64 dom0 kernels and not 32-on-64 domU
+ * or 64-bit kernels of any colour. The page tables for a 32-on-64 dom0 got
+ * allocated in the order: 'first L1','first L2', 'first L3', so the offset
+ * to the page table base is by two pages back. The initial domain if it is
+ * 32-bit and runs under a 64-bit hypervisor should _NOT_ use two of the
+ * pages preceding pt_base and mark them as reserved/unused.
+ */
+#ifdef XEN_HAVE_PV_GUEST_ENTRY
+struct start_info {
+ /* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME. */
+ char magic[32]; /* "xen-<version>-<platform>". */
+ unsigned long nr_pages; /* Total pages allocated to this domain. */
+ unsigned long shared_info; /* MACHINE address of shared info struct. */
+ uint32_t flags; /* SIF_xxx flags. */
+ xen_pfn_t store_mfn; /* MACHINE page number of shared page. */
+ uint32_t store_evtchn; /* Event channel for store communication. */
+ union {
+ struct {
+ xen_pfn_t mfn; /* MACHINE page number of console page. */
+ uint32_t evtchn; /* Event channel for console page. */
+ } domU;
+ struct {
+ uint32_t info_off; /* Offset of console_info struct. */
+ uint32_t info_size; /* Size of console_info struct from start.*/
+ } dom0;
+ } console;
+ /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */
+ unsigned long pt_base; /* VIRTUAL address of page directory. */
+ unsigned long nr_pt_frames; /* Number of bootstrap p.t. frames. */
+ unsigned long mfn_list; /* VIRTUAL address of page-frame list. */
+ unsigned long mod_start; /* VIRTUAL address of pre-loaded module */
+ /* (PFN of pre-loaded module if */
+ /* SIF_MOD_START_PFN set in flags). */
+ unsigned long mod_len; /* Size (bytes) of pre-loaded module. */
+#define MAX_GUEST_CMDLINE 1024
+ int8_t cmd_line[MAX_GUEST_CMDLINE];
+ /* The pfn range here covers both page table and p->m table frames. */
+ unsigned long first_p2m_pfn;/* 1st pfn forming initial P->M table. */
+ unsigned long nr_p2m_frames;/* # of pfns forming initial P->M table. */
+};
+typedef struct start_info start_info_t;
+
+/* New console union for dom0 introduced in 0x00030203. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030203
+#define console_mfn console.domU.mfn
+#define console_evtchn console.domU.evtchn
+#endif
+#endif /* XEN_HAVE_PV_GUEST_ENTRY */
+
+/* These flags are passed in the 'flags' field of start_info_t. */
+#define SIF_PRIVILEGED (1<<0) /* Is the domain privileged? */
+#define SIF_INITDOMAIN (1<<1) /* Is this the initial control domain? */
+#define SIF_MULTIBOOT_MOD (1<<2) /* Is mod_start a multiboot module? */
+#define SIF_MOD_START_PFN (1<<3) /* Is mod_start a PFN? */
+#define SIF_PM_MASK (0xFF<<8) /* reserve 1 byte for xen-pm options */
+
+/*
+ * A multiboot module is a package containing modules very similar to a
+ * multiboot module array. The only differences are:
+ * - the array of module descriptors is by convention simply at the beginning
+ * of the multiboot module,
+ * - addresses in the module descriptors are based on the beginning of the
+ * multiboot module,
+ * - the number of modules is determined by a termination descriptor that has
+ * mod_start == 0.
+ *
+ * This permits to both build it statically and reference it in a configuration
+ * file, and let the PV guest easily rebase the addresses to virtual addresses
+ * and at the same time count the number of modules.
+ */
+struct xen_multiboot_mod_list
+{
+ /* Address of first byte of the module */
+ uint32_t mod_start;
+ /* Address of last byte of the module (inclusive) */
+ uint32_t mod_end;
+ /* Address of zero-terminated command line */
+ uint32_t cmdline;
+ /* Unused, must be zero */
+ uint32_t pad;
+};
+/*
+ * `incontents 200 startofday_dom0_console Dom0_console
+ *
+ * The console structure in start_info.console.dom0
+ *
+ * This structure includes a variety of information required to
+ * have a working VGA/VESA console.
+ */
+typedef struct dom0_vga_console_info {
+ uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */
+#define XEN_VGATYPE_TEXT_MODE_3 0x03
+#define XEN_VGATYPE_VESA_LFB 0x23
+#define XEN_VGATYPE_EFI_LFB 0x70
+
+ union {
+ struct {
+ /* Font height, in pixels. */
+ uint16_t font_height;
+ /* Cursor location (column, row). */
+ uint16_t cursor_x, cursor_y;
+ /* Number of rows and columns (dimensions in characters). */
+ uint16_t rows, columns;
+ } text_mode_3;
+
+ struct {
+ /* Width and height, in pixels. */
+ uint16_t width, height;
+ /* Bytes per scan line. */
+ uint16_t bytes_per_line;
+ /* Bits per pixel. */
+ uint16_t bits_per_pixel;
+ /* LFB physical address, and size (in units of 64kB). */
+ uint32_t lfb_base;
+ uint32_t lfb_size;
+ /* RGB mask offsets and sizes, as defined by VBE 1.2+ */
+ uint8_t red_pos, red_size;
+ uint8_t green_pos, green_size;
+ uint8_t blue_pos, blue_size;
+ uint8_t rsvd_pos, rsvd_size;
+#if __XEN_INTERFACE_VERSION__ >= 0x00030206
+ /* VESA capabilities (offset 0xa, VESA command 0x4f00). */
+ uint32_t gbl_caps;
+ /* Mode attributes (offset 0x0, VESA command 0x4f01). */
+ uint16_t mode_attrs;
+#endif
+ } vesa_lfb;
+ } u;
+} dom0_vga_console_info_t;
+#define xen_vga_console_info dom0_vga_console_info
+#define xen_vga_console_info_t dom0_vga_console_info_t
+
+typedef uint8_t xen_domain_handle_t[16];
+
+/* Turn a plain number into a C unsigned long constant. */
+#define __mk_unsigned_long(x) x ## UL
+#define mk_unsigned_long(x) __mk_unsigned_long(x)
+
+__DEFINE_XEN_GUEST_HANDLE(uint8, uint8_t);
+__DEFINE_XEN_GUEST_HANDLE(uint16, uint16_t);
+__DEFINE_XEN_GUEST_HANDLE(uint32, uint32_t);
+__DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
+
+#else /* __ASSEMBLY__ */
+
+/* In assembly code we cannot use C numeric constant suffixes. */
+#define mk_unsigned_long(x) x
+
+#endif /* !__ASSEMBLY__ */
+
+/* Default definitions for macros used by domctl/sysctl. */
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+#ifndef uint64_aligned_t
+#define uint64_aligned_t uint64_t
+#endif
+#ifndef XEN_GUEST_HANDLE_64
+#define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name)
+#endif
+
+#ifndef __ASSEMBLY__
+struct xenctl_bitmap {
+ XEN_GUEST_HANDLE_64(uint8) bitmap;
+ uint32_t nr_bits;
+};
+#endif
+
+#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+
+#endif /* __XEN_PUBLIC_XEN_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (C) IBM Corp. 2006
+ */
+
+#ifndef _XEN_XENCOMM_H_
+#define _XEN_XENCOMM_H_
+
+/* A xencomm descriptor is a scatter/gather list containing physical
+ * addresses corresponding to a virtually contiguous memory area. The
+ * hypervisor translates these physical addresses to machine addresses to copy
+ * to and from the virtually contiguous area.
+ */
+
+#define XENCOMM_MAGIC 0x58434F4D /* 'XCOM' */
+#define XENCOMM_INVALID (~0UL)
+
+struct xencomm_desc {
+ uint32_t magic;
+ uint32_t nr_addrs; /* the number of entries in address[] */
+ uint64_t address[0];
+};
+
+#endif /* _XEN_XENCOMM_H_ */
--- /dev/null
+/******************************************************************************
+ * xenoprof.h
+ *
+ * Interface for enabling system wide profiling based on hardware performance
+ * counters
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (C) 2005 Hewlett-Packard Co.
+ * Written by Aravind Menon & Jose Renato Santos
+ */
+
+#ifndef __XEN_PUBLIC_XENOPROF_H__
+#define __XEN_PUBLIC_XENOPROF_H__
+
+#include "xen.h"
+
+/*
+ * Commands to HYPERVISOR_xenoprof_op().
+ */
+#define XENOPROF_init 0
+#define XENOPROF_reset_active_list 1
+#define XENOPROF_reset_passive_list 2
+#define XENOPROF_set_active 3
+#define XENOPROF_set_passive 4
+#define XENOPROF_reserve_counters 5
+#define XENOPROF_counter 6
+#define XENOPROF_setup_events 7
+#define XENOPROF_enable_virq 8
+#define XENOPROF_start 9
+#define XENOPROF_stop 10
+#define XENOPROF_disable_virq 11
+#define XENOPROF_release_counters 12
+#define XENOPROF_shutdown 13
+#define XENOPROF_get_buffer 14
+#define XENOPROF_set_backtrace 15
+
+/* AMD IBS support */
+#define XENOPROF_get_ibs_caps 16
+#define XENOPROF_ibs_counter 17
+#define XENOPROF_last_op 17
+
+#define MAX_OPROF_EVENTS 32
+#define MAX_OPROF_DOMAINS 25
+#define XENOPROF_CPU_TYPE_SIZE 64
+
+/* Xenoprof performance events (not Xen events) */
+struct event_log {
+ uint64_t eip;
+ uint8_t mode;
+ uint8_t event;
+};
+
+/* PC value that indicates a special code */
+#define XENOPROF_ESCAPE_CODE (~0ULL)
+/* Transient events for the xenoprof->oprofile cpu buf */
+#define XENOPROF_TRACE_BEGIN 1
+
+/* Xenoprof buffer shared between Xen and domain - 1 per VCPU */
+struct xenoprof_buf {
+ uint32_t event_head;
+ uint32_t event_tail;
+ uint32_t event_size;
+ uint32_t vcpu_id;
+ uint64_t xen_samples;
+ uint64_t kernel_samples;
+ uint64_t user_samples;
+ uint64_t lost_samples;
+ struct event_log event_log[1];
+};
+#ifndef __XEN__
+typedef struct xenoprof_buf xenoprof_buf_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_buf_t);
+#endif
+
+struct xenoprof_init {
+ int32_t num_events;
+ int32_t is_primary;
+ char cpu_type[XENOPROF_CPU_TYPE_SIZE];
+};
+typedef struct xenoprof_init xenoprof_init_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_init_t);
+
+struct xenoprof_get_buffer {
+ int32_t max_samples;
+ int32_t nbuf;
+ int32_t bufsize;
+ uint64_t buf_gmaddr;
+};
+typedef struct xenoprof_get_buffer xenoprof_get_buffer_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_get_buffer_t);
+
+struct xenoprof_counter {
+ uint32_t ind;
+ uint64_t count;
+ uint32_t enabled;
+ uint32_t event;
+ uint32_t hypervisor;
+ uint32_t kernel;
+ uint32_t user;
+ uint64_t unit_mask;
+};
+typedef struct xenoprof_counter xenoprof_counter_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_counter_t);
+
+typedef struct xenoprof_passive {
+ uint16_t domain_id;
+ int32_t max_samples;
+ int32_t nbuf;
+ int32_t bufsize;
+ uint64_t buf_gmaddr;
+} xenoprof_passive_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t);
+
+struct xenoprof_ibs_counter {
+ uint64_t op_enabled;
+ uint64_t fetch_enabled;
+ uint64_t max_cnt_fetch;
+ uint64_t max_cnt_op;
+ uint64_t rand_en;
+ uint64_t dispatched_ops;
+};
+typedef struct xenoprof_ibs_counter xenoprof_ibs_counter_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_ibs_counter_t);
+
+#endif /* __XEN_PUBLIC_XENOPROF_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/*
+ * This file contains the flask_op hypercall commands and definitions.
+ *
+ * Author: George Coker, <gscoker@alpha.ncsc.mil>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __FLASK_OP_H__
+#define __FLASK_OP_H__
+
+#define XEN_FLASK_INTERFACE_VERSION 1
+
+struct xen_flask_load {
+ XEN_GUEST_HANDLE(char) buffer;
+ uint32_t size;
+};
+
+struct xen_flask_setenforce {
+ uint32_t enforcing;
+};
+
+struct xen_flask_sid_context {
+ /* IN/OUT: sid to convert to/from string */
+ uint32_t sid;
+ /* IN: size of the context buffer
+ * OUT: actual size of the output context string
+ */
+ uint32_t size;
+ XEN_GUEST_HANDLE(char) context;
+};
+
+struct xen_flask_access {
+ /* IN: access request */
+ uint32_t ssid;
+ uint32_t tsid;
+ uint32_t tclass;
+ uint32_t req;
+ /* OUT: AVC data */
+ uint32_t allowed;
+ uint32_t audit_allow;
+ uint32_t audit_deny;
+ uint32_t seqno;
+};
+
+struct xen_flask_transition {
+ /* IN: transition SIDs and class */
+ uint32_t ssid;
+ uint32_t tsid;
+ uint32_t tclass;
+ /* OUT: new SID */
+ uint32_t newsid;
+};
+
+struct xen_flask_userlist {
+ /* IN: starting SID for list */
+ uint32_t start_sid;
+ /* IN: size of user string and output buffer
+ * OUT: number of SIDs returned */
+ uint32_t size;
+ union {
+ /* IN: user to enumerate SIDs */
+ XEN_GUEST_HANDLE(char) user;
+ /* OUT: SID list */
+ XEN_GUEST_HANDLE(uint32) sids;
+ } u;
+};
+
+struct xen_flask_boolean {
+ /* IN/OUT: numeric identifier for boolean [GET/SET]
+ * If -1, name will be used and bool_id will be filled in. */
+ uint32_t bool_id;
+ /* OUT: current enforcing value of boolean [GET/SET] */
+ uint8_t enforcing;
+ /* OUT: pending value of boolean [GET/SET] */
+ uint8_t pending;
+ /* IN: new value of boolean [SET] */
+ uint8_t new_value;
+ /* IN: commit new value instead of only setting pending [SET] */
+ uint8_t commit;
+ /* IN: size of boolean name buffer [GET/SET]
+ * OUT: actual size of name [GET only] */
+ uint32_t size;
+ /* IN: if bool_id is -1, used to find boolean [GET/SET]
+ * OUT: textual name of boolean [GET only]
+ */
+ XEN_GUEST_HANDLE(char) name;
+};
+
+struct xen_flask_setavc_threshold {
+ /* IN */
+ uint32_t threshold;
+};
+
+struct xen_flask_hash_stats {
+ /* OUT */
+ uint32_t entries;
+ uint32_t buckets_used;
+ uint32_t buckets_total;
+ uint32_t max_chain_len;
+};
+
+struct xen_flask_cache_stats {
+ /* IN */
+ uint32_t cpu;
+ /* OUT */
+ uint32_t lookups;
+ uint32_t hits;
+ uint32_t misses;
+ uint32_t allocations;
+ uint32_t reclaims;
+ uint32_t frees;
+};
+
+struct xen_flask_ocontext {
+ /* IN */
+ uint32_t ocon;
+ uint32_t sid;
+ uint64_t low, high;
+};
+
+struct xen_flask_peersid {
+ /* IN */
+ evtchn_port_t evtchn;
+ /* OUT */
+ uint32_t sid;
+};
+
+struct xen_flask_relabel {
+ /* IN */
+ uint32_t domid;
+ uint32_t sid;
+};
+
+struct xen_flask_op {
+ uint32_t cmd;
+#define FLASK_LOAD 1
+#define FLASK_GETENFORCE 2
+#define FLASK_SETENFORCE 3
+#define FLASK_CONTEXT_TO_SID 4
+#define FLASK_SID_TO_CONTEXT 5
+#define FLASK_ACCESS 6
+#define FLASK_CREATE 7
+#define FLASK_RELABEL 8
+#define FLASK_USER 9
+#define FLASK_POLICYVERS 10
+#define FLASK_GETBOOL 11
+#define FLASK_SETBOOL 12
+#define FLASK_COMMITBOOLS 13
+#define FLASK_MLS 14
+#define FLASK_DISABLE 15
+#define FLASK_GETAVC_THRESHOLD 16
+#define FLASK_SETAVC_THRESHOLD 17
+#define FLASK_AVC_HASHSTATS 18
+#define FLASK_AVC_CACHESTATS 19
+#define FLASK_MEMBER 20
+#define FLASK_ADD_OCONTEXT 21
+#define FLASK_DEL_OCONTEXT 22
+#define FLASK_GET_PEER_SID 23
+#define FLASK_RELABEL_DOMAIN 24
+ uint32_t interface_version; /* XEN_FLASK_INTERFACE_VERSION */
+ union {
+ struct xen_flask_load load;
+ struct xen_flask_setenforce enforce;
+ /* FLASK_CONTEXT_TO_SID and FLASK_SID_TO_CONTEXT */
+ struct xen_flask_sid_context sid_context;
+ struct xen_flask_access access;
+ /* FLASK_CREATE, FLASK_RELABEL, FLASK_MEMBER */
+ struct xen_flask_transition transition;
+ struct xen_flask_userlist userlist;
+ /* FLASK_GETBOOL, FLASK_SETBOOL */
+ struct xen_flask_boolean boolean;
+ struct xen_flask_setavc_threshold setavc_threshold;
+ struct xen_flask_hash_stats hash_stats;
+ struct xen_flask_cache_stats cache_stats;
+ /* FLASK_ADD_OCONTEXT, FLASK_DEL_OCONTEXT */
+ struct xen_flask_ocontext ocontext;
+ struct xen_flask_peersid peersid;
+ struct xen_flask_relabel relabel;
+ } u;
+};
+typedef struct xen_flask_op xen_flask_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_flask_op_t);
+
+#endif
--- /dev/null
+#ifndef XENBUS_H__
+#define XENBUS_H__
+
+#include <xen/io/xenbus.h>
+
+typedef unsigned long xenbus_transaction_t;
+#define XBT_NIL ((xenbus_transaction_t)0)
+
+#ifdef CONFIG_XENBUS
+/* Initialize the XenBus system. */
+void init_xenbus(void);
+#else
+static inline void init_xenbus(void)
+{
+}
+#endif
+
+/* Read the value associated with a path. Returns a malloc'd error
+ string on failure and sets *value to NULL. On success, *value is
+ set to a malloc'd copy of the value. */
+char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value);
+
+/* Watch event queue */
+struct xenbus_event {
+ /* Keep these two as this for xs.c */
+ char *path;
+ char *token;
+ struct xenbus_event *next;
+};
+typedef struct xenbus_event *xenbus_event_queue;
+
+char *xenbus_watch_path_token(xenbus_transaction_t xbt, const char *path, const char *token, xenbus_event_queue *events);
+char *xenbus_unwatch_path_token(xenbus_transaction_t xbt, const char *path, const char *token);
+extern struct wait_queue_head xenbus_watch_queue;
+void xenbus_wait_for_watch(xenbus_event_queue *queue);
+char **xenbus_wait_for_watch_return(xenbus_event_queue *queue);
+char* xenbus_wait_for_value(const char *path, const char *value, xenbus_event_queue *queue);
+char *xenbus_wait_for_state_change(const char* path, XenbusState *state, xenbus_event_queue *queue);
+char *xenbus_switch_state(xenbus_transaction_t xbt, const char* path, XenbusState state);
+
+/* When no token is provided, use a global queue. */
+#define XENBUS_WATCH_PATH_TOKEN "xenbus_watch_path"
+extern xenbus_event_queue xenbus_events;
+#define xenbus_watch_path(xbt, path) xenbus_watch_path_token(xbt, path, XENBUS_WATCH_PATH_TOKEN, NULL)
+#define xenbus_unwatch_path(xbt, path) xenbus_unwatch_path_token(xbt, path, XENBUS_WATCH_PATH_TOKEN)
+
+
+/* Associates a value with a path. Returns a malloc'd error string on
+ failure. */
+char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value);
+
+struct write_req {
+ const void *data;
+ unsigned len;
+};
+
+/* Send a message to xenbus, in the same fashion as xb_write, and
+ block waiting for a reply. The reply is malloced and should be
+ freed by the caller. */
+struct xsd_sockmsg *
+xenbus_msg_reply(int type,
+ xenbus_transaction_t trans,
+ struct write_req *io,
+ int nr_reqs);
+
+/* Removes the value associated with a path. Returns a malloc'd error
+ string on failure. */
+char *xenbus_rm(xenbus_transaction_t xbt, const char *path);
+
+/* List the contents of a directory. Returns a malloc'd error string
+ on failure and sets *contents to NULL. On success, *contents is
+ set to a malloc'd array of pointers to malloc'd strings. The array
+ is NULL terminated. May block. */
+char *xenbus_ls(xenbus_transaction_t xbt, const char *prefix, char ***contents);
+
+/* Reads permissions associated with a path. Returns a malloc'd error
+ string on failure and sets *value to NULL. On success, *value is
+ set to a malloc'd copy of the value. */
+char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value);
+
+/* Sets the permissions associated with a path. Returns a malloc'd
+ error string on failure. */
+char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t dom, char perm);
+
+/* Start a xenbus transaction. Returns the transaction in xbt on
+ success or a malloc'd error string otherwise. */
+char *xenbus_transaction_start(xenbus_transaction_t *xbt);
+
+/* End a xenbus transaction. Returns a malloc'd error string if it
+ fails. abort says whether the transaction should be aborted.
+ Returns 1 in *retry iff the transaction should be retried. */
+char *xenbus_transaction_end(xenbus_transaction_t, int abort,
+ int *retry);
+
+/* Read path and parse it as an integer. Returns -1 on error. */
+int xenbus_read_integer(const char *path);
+
+/* Read path and parse it as 16 byte uuid. Returns 1 if
+ * read and parsing were successful, 0 if not */
+int xenbus_read_uuid(const char* path, unsigned char uuid[16]);
+
+/* Contraction of snprintf and xenbus_write(path/node). */
+char* xenbus_printf(xenbus_transaction_t xbt,
+ const char* node, const char* path,
+ const char* fmt, ...)
+ __attribute__((__format__(printf, 4, 5)));
+
+/* Utility function to figure out our domain id */
+domid_t xenbus_get_self_id(void);
+
+#ifdef CONFIG_XENBUS
+/* Reset the XenBus system. */
+void fini_xenbus(void);
+#else
+static inline void fini_xenbus(void)
+{
+}
+#endif
+
+#endif /* XENBUS_H__ */
--- /dev/null
+#ifndef __XMALLOC_H__
+#define __XMALLOC_H__
+
+#ifdef HAVE_LIBC
+
+#include <stdlib.h>
+#include <malloc.h>
+/* Allocate space for typed object. */
+#define _xmalloc(size, align) memalign(align, size)
+#define xfree(ptr) free(ptr)
+
+#else
+
+#include <limits.h>
+
+#define DEFAULT_ALIGN (sizeof(unsigned long))
+
+extern void *malloc(size_t size);
+extern void *realloc(void *ptr, size_t size);
+extern void free(void *ptr);
+
+/* Free memory from any xmalloc*() call. */
+extern void xfree(const void *);
+
+/* Underlying functions */
+extern void *_xmalloc(size_t size, size_t align);
+
+#endif
+
+static inline void *_xmalloc_array(size_t size, size_t align, size_t num)
+{
+ /* Check for overflow. */
+ if (size && num > UINT_MAX / size)
+ return NULL;
+ return _xmalloc(size * num, align);
+}
+
+/* Allocate space for typed object. */
+#define xmalloc(_type) ((_type *)_xmalloc(sizeof(_type), __alignof__(_type)))
+
+/* Allocate space for array of typed objects. */
+#define xmalloc_array(_type, _num) ((_type *)_xmalloc_array(sizeof(_type), __alignof__(_type), _num))
+
+#endif /* __XMALLOC_H__ */
--- /dev/null
+/******************************************************************************
+ * kernel.c
+ *
+ * Assorted crap goes here, including the initial C entry point, jumped at
+ * from head.S.
+ *
+ * Copyright (c) 2002-2003, K A Fraser & R Neugebauer
+ * Copyright (c) 2005, Grzegorz Milos, Intel Research Cambridge
+ * Copyright (c) 2006, Robert Kaiser, FH Wiesbaden
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <mini-os/os.h>
+#include <mini-os/kernel.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/mm.h>
+#include <mini-os/events.h>
+#include <mini-os/time.h>
+#include <mini-os/types.h>
+#include <mini-os/lib.h>
+#include <mini-os/sched.h>
+#include <mini-os/xenbus.h>
+#include <mini-os/gnttab.h>
+#include <mini-os/netfront.h>
+#include <mini-os/blkfront.h>
+#include <mini-os/fbfront.h>
+#include <mini-os/pcifront.h>
+#include <mini-os/xmalloc.h>
+#include <fcntl.h>
+#include <xen/features.h>
+#include <xen/version.h>
+
+uint8_t xen_features[XENFEAT_NR_SUBMAPS * 32];
+
+void setup_xen_features(void)
+{
+ xen_feature_info_t fi;
+ int i, j;
+
+ for (i = 0; i < XENFEAT_NR_SUBMAPS; i++)
+ {
+ fi.submap_idx = i;
+ if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0)
+ break;
+
+ for (j=0; j<32; j++)
+ xen_features[i*32+j] = !!(fi.submap & 1<<j);
+ }
+}
+
+#ifdef CONFIG_XENBUS
+/* This should be overridden by the application we are linked against. */
+__attribute__((weak)) void app_shutdown(unsigned reason)
+{
+ struct sched_shutdown sched_shutdown = { .reason = reason };
+ printk("Shutdown requested: %d\n", reason);
+ HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
+}
+
+static void shutdown_thread(void *p)
+{
+ const char *path = "control/shutdown";
+ const char *token = path;
+ xenbus_event_queue events = NULL;
+ char *shutdown = NULL, *err;
+ unsigned int shutdown_reason;
+ xenbus_watch_path_token(XBT_NIL, path, token, &events);
+ while ((err = xenbus_read(XBT_NIL, path, &shutdown)) != NULL || !strcmp(shutdown, ""))
+ {
+ free(err);
+ free(shutdown);
+ shutdown = NULL;
+ xenbus_wait_for_watch(&events);
+ }
+ err = xenbus_unwatch_path_token(XBT_NIL, path, token);
+ free(err);
+ err = xenbus_write(XBT_NIL, path, "");
+ free(err);
+ printk("Shutting down (%s)\n", shutdown);
+
+ if (!strcmp(shutdown, "poweroff"))
+ shutdown_reason = SHUTDOWN_poweroff;
+ else if (!strcmp(shutdown, "reboot"))
+ shutdown_reason = SHUTDOWN_reboot;
+ else
+ /* Unknown */
+ shutdown_reason = SHUTDOWN_crash;
+ app_shutdown(shutdown_reason);
+ free(shutdown);
+}
+#endif
+
+
+/* This should be overridden by the application we are linked against. */
+__attribute__((weak)) int app_main(start_info_t *si)
+{
+ printk("kernel.c: dummy main: start_info=%p\n", si);
+ return 0;
+}
+
+void start_kernel(void)
+{
+ /* Set up events. */
+ init_events();
+
+ /* ENABLE EVENT DELIVERY. This is disabled at start of day. */
+ local_irq_enable();
+
+ setup_xen_features();
+
+ /* Init memory management. */
+ init_mm();
+
+ /* Init time and timers. */
+ init_time();
+
+ /* Init the console driver. */
+ init_console();
+
+ /* Init grant tables */
+ init_gnttab();
+
+ /* Init scheduler. */
+ init_sched();
+
+ /* Init XenBus */
+ init_xenbus();
+
+#ifdef CONFIG_XENBUS
+ create_thread("shutdown", shutdown_thread, NULL);
+#endif
+
+ /* Call (possibly overridden) app_main() */
+ app_main(&start_info);
+
+ /* Everything initialised, start idle thread */
+ run_idle_thread();
+}
+
+void stop_kernel(void)
+{
+ /* TODO: fs import */
+
+ local_irq_disable();
+
+ /* Reset grant tables */
+ fini_gnttab();
+
+ /* Reset XenBus */
+ fini_xenbus();
+
+ /* Reset timers */
+ fini_time();
+
+ /* Reset memory management. */
+ fini_mm();
+
+ /* Reset events. */
+ fini_events();
+
+ /* Reset arch details */
+ arch_fini();
+}
+
+/*
+ * do_exit: This is called whenever an IRET fails in entry.S.
+ * This will generally be because an application has got itself into
+ * a really bad state (probably a bad CS or SS). It must be killed.
+ * Of course, minimal OS doesn't have applications :-)
+ */
+
+void do_exit(void)
+{
+ printk("Do_exit called!\n");
+ arch_do_exit();
+ for( ;; )
+ {
+ struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_crash };
+ HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
+ }
+}
--- /dev/null
+#ifndef HAVE_LIBC
+#include <ctype.h>
+
+unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
+#endif
--- /dev/null
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: math.c
+ * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
+ * Changes:
+ *
+ * Date: Aug 2003
+ *
+ * Environment: Xen Minimal OS
+ * Description: Library functions for 64bit arith and other
+ * from freebsd, files in sys/libkern/ (qdivrem.c, etc)
+ *
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+*/
+
+#include <mini-os/types.h>
+#include <mini-os/lib.h>
+#include <mini-os/time.h>
+
+/* XXX RN: Yuck hardcoded endianess :) */
+#define _QUAD_HIGHWORD 1
+#define _QUAD_LOWWORD 0
+
+/*
+ * From
+ * @(#)quad.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * Depending on the desired operation, we view a `long long' (aka quad_t) in
+ * one or more of the following formats.
+ */
+union uu {
+ quad_t q; /* as a (signed) quad */
+ quad_t uq; /* as an unsigned quad */
+ int32_t sl[2]; /* as two signed longs */
+ uint32_t ul[2]; /* as two unsigned longs */
+};
+
+/*
+ * Define high and low longwords.
+ */
+#define H _QUAD_HIGHWORD
+#define L _QUAD_LOWWORD
+
+/*
+ * Total number of bits in an quad_t and in the pieces that make it up.
+ * These are used for shifting, and also below for halfword extraction
+ * and assembly.
+ */
+#ifndef HAVE_LIBC
+#define CHAR_BIT 8 /* number of bits in a char */
+#endif
+#define QUAD_BITS (sizeof(quad_t) * CHAR_BIT)
+#define LONG_BITS (sizeof(int32_t) * CHAR_BIT)
+#define HALF_BITS (sizeof(int32_t) * CHAR_BIT / 2)
+
+/*
+ * Extract high and low shortwords from longword, and move low shortword of
+ * longword to upper half of int32_t, i.e., produce the upper longword of
+ * ((quad_t)(x) << (number_of_bits_in_long/2)). (`x' must actually be uint32_t.)
+ *
+ * These are used in the multiply code, to split a longword into upper
+ * and lower halves, and to reassemble a product as a quad_t, shifted left
+ * (sizeof(int32_t)*CHAR_BIT/2).
+ */
+#define HHALF(x) ((x) >> HALF_BITS)
+#define LHALF(x) ((x) & ((1UL << HALF_BITS) - 1))
+#define LHUP(x) ((x) << HALF_BITS)
+
+
+/*
+ * From
+ * qdivrem.c
+ */
+
+/*
+ * Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed),
+ * section 4.3.1, pp. 257--259.
+ */
+#define B (1UL << HALF_BITS) /* digit base */
+
+/* Combine two `digits' to make a single two-digit number. */
+#define COMBINE(a, b) (((uint32_t)(a) << HALF_BITS) | (b))
+
+/* select a type for digits in base B: */
+typedef uint16_t digit;
+
+/*
+ * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
+ * `fall out' the left (there never will be any such anyway).
+ * We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS.
+ */
+static void
+shl(register digit *p, register int len, register int sh)
+{
+ register int i;
+
+ for (i = 0; i < len; i++)
+ p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh));
+ p[i] = LHALF(p[i] << sh);
+}
+
+/*
+ * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
+ *
+ * We do this in base 2-sup-HALF_BITS, so that all intermediate products
+ * fit within uint32_t. As a consequence, the maximum length dividend and
+ * divisor are 4 `digits' in this base (they are shorter if they have
+ * leading zeros).
+ */
+u_quad_t
+__qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq)
+{
+ union uu tmp;
+ digit *u, *v, *q;
+ register digit v1, v2;
+ uint32_t qhat, rhat, t;
+ int m, n, d, j, i;
+ digit uspace[5], vspace[5], qspace[5];
+
+ /*
+ * Take care of special cases: divide by zero, and u < v.
+ */
+ if (vq == 0) {
+ /* divide by zero. */
+ static volatile const unsigned int zero = 0;
+
+ tmp.ul[H] = tmp.ul[L] = 1 / zero;
+ if (arq)
+ *arq = uq;
+ return (tmp.q);
+ }
+ if (uq < vq) {
+ if (arq)
+ *arq = uq;
+ return (0);
+ }
+ u = &uspace[0];
+ v = &vspace[0];
+ q = &qspace[0];
+
+ /*
+ * Break dividend and divisor into digits in base B, then
+ * count leading zeros to determine m and n. When done, we
+ * will have:
+ * u = (u[1]u[2]...u[m+n]) sub B
+ * v = (v[1]v[2]...v[n]) sub B
+ * v[1] != 0
+ * 1 < n <= 4 (if n = 1, we use a different division algorithm)
+ * m >= 0 (otherwise u < v, which we already checked)
+ * m + n = 4
+ * and thus
+ * m = 4 - n <= 2
+ */
+ tmp.uq = uq;
+ u[0] = 0;
+ u[1] = HHALF(tmp.ul[H]);
+ u[2] = LHALF(tmp.ul[H]);
+ u[3] = HHALF(tmp.ul[L]);
+ u[4] = LHALF(tmp.ul[L]);
+ tmp.uq = vq;
+ v[1] = HHALF(tmp.ul[H]);
+ v[2] = LHALF(tmp.ul[H]);
+ v[3] = HHALF(tmp.ul[L]);
+ v[4] = LHALF(tmp.ul[L]);
+ for (n = 4; v[1] == 0; v++) {
+ if (--n == 1) {
+ uint32_t rbj; /* r*B+u[j] (not root boy jim) */
+ digit q1, q2, q3, q4;
+
+ /*
+ * Change of plan, per exercise 16.
+ * r = 0;
+ * for j = 1..4:
+ * q[j] = floor((r*B + u[j]) / v),
+ * r = (r*B + u[j]) % v;
+ * We unroll this completely here.
+ */
+ t = v[2]; /* nonzero, by definition */
+ q1 = u[1] / t;
+ rbj = COMBINE(u[1] % t, u[2]);
+ q2 = rbj / t;
+ rbj = COMBINE(rbj % t, u[3]);
+ q3 = rbj / t;
+ rbj = COMBINE(rbj % t, u[4]);
+ q4 = rbj / t;
+ if (arq)
+ *arq = rbj % t;
+ tmp.ul[H] = COMBINE(q1, q2);
+ tmp.ul[L] = COMBINE(q3, q4);
+ return (tmp.q);
+ }
+ }
+
+ /*
+ * By adjusting q once we determine m, we can guarantee that
+ * there is a complete four-digit quotient at &qspace[1] when
+ * we finally stop.
+ */
+ for (m = 4 - n; u[1] == 0; u++)
+ m--;
+ for (i = 4 - m; --i >= 0;)
+ q[i] = 0;
+ q += 4 - m;
+
+ /*
+ * Here we run Program D, translated from MIX to C and acquiring
+ * a few minor changes.
+ *
+ * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
+ */
+ d = 0;
+ for (t = v[1]; t < B / 2; t <<= 1)
+ d++;
+ if (d > 0) {
+ shl(&u[0], m + n, d); /* u <<= d */
+ shl(&v[1], n - 1, d); /* v <<= d */
+ }
+ /*
+ * D2: j = 0.
+ */
+ j = 0;
+ v1 = v[1]; /* for D3 -- note that v[1..n] are constant */
+ v2 = v[2]; /* for D3 */
+ do {
+ register digit uj0, uj1, uj2;
+
+ /*
+ * D3: Calculate qhat (\^q, in TeX notation).
+ * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
+ * let rhat = (u[j]*B + u[j+1]) mod v[1].
+ * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
+ * decrement qhat and increase rhat correspondingly.
+ * Note that if rhat >= B, v[2]*qhat < rhat*B.
+ */
+ uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
+ uj1 = u[j + 1]; /* for D3 only */
+ uj2 = u[j + 2]; /* for D3 only */
+ if (uj0 == v1) {
+ qhat = B;
+ rhat = uj1;
+ goto qhat_too_big;
+ } else {
+ uint32_t nn = COMBINE(uj0, uj1);
+ qhat = nn / v1;
+ rhat = nn % v1;
+ }
+ while (v2 * qhat > COMBINE(rhat, uj2)) {
+ qhat_too_big:
+ qhat--;
+ if ((rhat += v1) >= B)
+ break;
+ }
+ /*
+ * D4: Multiply and subtract.
+ * The variable `t' holds any borrows across the loop.
+ * We split this up so that we do not require v[0] = 0,
+ * and to eliminate a final special case.
+ */
+ for (t = 0, i = n; i > 0; i--) {
+ t = u[i + j] - v[i] * qhat - t;
+ u[i + j] = LHALF(t);
+ t = (B - HHALF(t)) & (B - 1);
+ }
+ t = u[j] - t;
+ u[j] = LHALF(t);
+ /*
+ * D5: test remainder.
+ * There is a borrow if and only if HHALF(t) is nonzero;
+ * in that (rare) case, qhat was too large (by exactly 1).
+ * Fix it by adding v[1..n] to u[j..j+n].
+ */
+ if (HHALF(t)) {
+ qhat--;
+ for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
+ t += u[i + j] + v[i];
+ u[i + j] = LHALF(t);
+ t = HHALF(t);
+ }
+ u[j] = LHALF(u[j] + t);
+ }
+ q[j] = qhat;
+ } while (++j <= m); /* D7: loop on j. */
+
+ /*
+ * If caller wants the remainder, we have to calculate it as
+ * u[m..m+n] >> d (this is at most n digits and thus fits in
+ * u[m+1..m+n], but we may need more source digits).
+ */
+ if (arq) {
+ if (d) {
+ for (i = m + n; i > m; --i)
+ u[i] = (u[i] >> d) |
+ LHALF(u[i - 1] << (HALF_BITS - d));
+ u[i] = 0;
+ }
+ tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
+ tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
+ *arq = tmp.q;
+ }
+
+ tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+ tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+ return (tmp.q);
+}
+
+/*
+ * From
+ * divdi3.c
+ */
+
+/*
+ * Divide two signed quads.
+ * ??? if -1/2 should produce -1 on this machine, this code is wrong
+ */
+quad_t
+__divdi3(quad_t a, quad_t b)
+{
+ u_quad_t ua, ub, uq;
+ int neg;
+
+ if (a < 0)
+ ua = -(u_quad_t)a, neg = 1;
+ else
+ ua = a, neg = 0;
+ if (b < 0)
+ ub = -(u_quad_t)b, neg ^= 1;
+ else
+ ub = b;
+ uq = __qdivrem(ua, ub, (u_quad_t *)0);
+ return (neg ? -uq : uq);
+}
+
+/*
+ * From
+ * udivdi3.c
+ */
+
+/*
+ * Divide two unsigned quads.
+ */
+u_quad_t
+__udivdi3(u_quad_t a, u_quad_t b)
+{
+ return (__qdivrem(a, b, (u_quad_t *)0));
+}
+
+/*
+ * From
+ * umoddi3.c
+ */
+
+/*
+ * Return remainder after dividing two unsigned quads.
+ */
+u_quad_t
+__umoddi3(u_quad_t a, u_quad_t b)
+{
+ u_quad_t r;
+
+ (void)__qdivrem(a, b, &r);
+ return (r);
+}
+
+/*
+ * From
+ * moddi3.c
+ */
+
+/*
+ * Return remainder after dividing two signed quads.
+ *
+ * XXX
+ * If -1/2 should produce -1 on this machine, this code is wrong.
+ */
+quad_t
+__moddi3(quad_t a, quad_t b)
+{
+ u_quad_t ua, ub, ur;
+ int neg;
+
+ if (a < 0)
+ ua = -(u_quad_t)a, neg = 1;
+ else
+ ua = a, neg = 0;
+ if (b < 0)
+ ub = -(u_quad_t)b;
+ else
+ ub = b;
+ (void)__qdivrem(ua, ub, &ur);
+ return (neg ? -ur : ur);
+}
--- /dev/null
+/*
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: printf.c
+ * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
+ * Changes: Grzegorz Milos (gm281@cam.ac.uk)
+ *
+ * Date: Aug 2003, Aug 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: Library functions for printing
+ * (Linux port, mainly lib/vsprintf.c)
+ *
+ ****************************************************************************
+ */
+
+/*
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
+/*
+ * Wirzenius wrote this portably, Torvalds fucked it up :-)
+ */
+
+/*
+ * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
+ * - changed to provide snprintf and vsnprintf functions
+ * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
+ * - scnprintf and vscnprintf
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if !defined HAVE_LIBC
+
+#include <mini-os/os.h>
+#include <mini-os/types.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/lib.h>
+#include <mini-os/mm.h>
+#include <mini-os/ctype.h>
+#include <mini-os/posix/limits.h>
+
+/**
+ * simple_strtoul - convert a string to an unsigned long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
+{
+ unsigned long result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((*cp == 'x') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ }
+ while (isxdigit(*cp) &&
+ (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+/**
+ * simple_strtol - convert a string to a signed long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long simple_strtol(const char *cp,char **endp,unsigned int base)
+{
+ if(*cp=='-')
+ return -simple_strtoul(cp+1,endp,base);
+ return simple_strtoul(cp,endp,base);
+}
+
+/**
+ * simple_strtoull - convert a string to an unsigned long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
+{
+ unsigned long long result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((*cp == 'x') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ }
+ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+ ? toupper(*cp) : *cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+/**
+ * simple_strtoll - convert a string to a signed long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long long simple_strtoll(const char *cp,char **endp,unsigned int base)
+{
+ if(*cp=='-')
+ return -simple_strtoull(cp+1,endp,base);
+ return simple_strtoull(cp,endp,base);
+}
+
+static int skip_atoi(const char **s)
+{
+ int i=0;
+
+ while (isdigit(**s))
+ i = i*10 + *((*s)++) - '0';
+ return i;
+}
+
+#define ZEROPAD 1 /* pad with zero */
+#define SIGN 2 /* unsigned/signed long */
+#define PLUS 4 /* show plus */
+#define SPACE 8 /* space if plus */
+#define LEFT 16 /* left justified */
+#define SPECIAL 32 /* 0x */
+#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
+
+static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
+{
+ char c,sign,tmp[66];
+ const char *digits;
+ const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+ const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ int i;
+
+ digits = (type & LARGE) ? large_digits : small_digits;
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ if (base < 2 || base > 36)
+ return buf;
+ c = (type & ZEROPAD) ? '0' : ' ';
+ sign = 0;
+ if (type & SIGN) {
+ if (num < 0) {
+ sign = '-';
+ num = -num;
+ size--;
+ } else if (type & PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++]='0';
+ else
+ {
+ /* XXX KAF: force unsigned mod and div. */
+ unsigned long long num2=(unsigned long long)num;
+ unsigned int base2=(unsigned int)base;
+ while (num2 != 0) { tmp[i++] = digits[num2%base2]; num2 /= base2; }
+ }
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT))) {
+ while(size-->0) {
+ if (buf <= end)
+ *buf = ' ';
+ ++buf;
+ }
+ }
+ if (sign) {
+ if (buf <= end)
+ *buf = sign;
+ ++buf;
+ }
+ if (type & SPECIAL) {
+ if (base==8) {
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ } else if (base==16) {
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ if (buf <= end)
+ *buf = digits[33];
+ ++buf;
+ }
+ }
+ if (!(type & LEFT)) {
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = c;
+ ++buf;
+ }
+ }
+ while (i < precision--) {
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ }
+ while (i-- > 0) {
+ if (buf <= end)
+ *buf = tmp[i];
+ ++buf;
+ }
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = ' ';
+ ++buf;
+ }
+ return buf;
+}
+
+/**
+* vsnprintf - Format a string and place it in a buffer
+* @buf: The buffer to place the result into
+* @size: The size of the buffer, including the trailing null space
+* @fmt: The format string to use
+* @args: Arguments for the format string
+*
+* Call this function if you are already dealing with a va_list.
+* You probably want snprintf instead.
+ */
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+ int len;
+ unsigned long long num;
+ int i, base;
+ char *str, *end, c;
+ const char *s;
+
+ int flags; /* flags to number() */
+
+ int field_width; /* width of output field */
+ int precision; /* min. # of digits for integers; max
+ number of chars for from string */
+ int qualifier; /* 'h', 'l', or 'L' for integer fields */
+ /* 'z' support added 23/7/1999 S.H. */
+ /* 'z' changed to 'Z' --davidm 1/25/99 */
+
+ str = buf;
+ end = buf + size - 1;
+
+ if (end < buf - 1) {
+ end = ((void *) -1);
+ size = end - buf + 1;
+ }
+
+ for (; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+ if (str <= end)
+ *str = *fmt;
+ ++str;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+ repeat:
+ ++fmt; /* this also skips first '%' */
+ switch (*fmt) {
+ case '-': flags |= LEFT; goto repeat;
+ case '+': flags |= PLUS; goto repeat;
+ case ' ': flags |= SPACE; goto repeat;
+ case '#': flags |= SPECIAL; goto repeat;
+ case '0': flags |= ZEROPAD; goto repeat;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (isdigit(*fmt))
+ field_width = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ field_width = va_arg(args, int);
+ if (field_width < 0) {
+ field_width = -field_width;
+ flags |= LEFT;
+ }
+ }
+
+ /* get the precision */
+ precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (isdigit(*fmt))
+ precision = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ precision = va_arg(args, int);
+ }
+ if (precision < 0)
+ precision = 0;
+ }
+
+ /* get the conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
+ qualifier = *fmt;
+ ++fmt;
+ if (qualifier == 'l' && *fmt == 'l') {
+ qualifier = 'L';
+ ++fmt;
+ }
+ }
+ if (*fmt == 'q') {
+ qualifier = 'L';
+ ++fmt;
+ }
+
+ /* default base */
+ base = 10;
+
+ switch (*fmt) {
+ case 'c':
+ if (!(flags & LEFT)) {
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ }
+ c = (unsigned char) va_arg(args, int);
+ if (str <= end)
+ *str = c;
+ ++str;
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ continue;
+
+ case 's':
+ s = va_arg(args, char *);
+ if (!s)
+ s = "<NULL>";
+
+ len = strnlen(s, precision);
+
+ if (!(flags & LEFT)) {
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = *s;
+ ++str; ++s;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ continue;
+
+ case 'p':
+ if (field_width == -1) {
+ field_width = 2*sizeof(void *);
+ flags |= ZEROPAD;
+ }
+ str = number(str, end,
+ (unsigned long) va_arg(args, void *),
+ 16, field_width, precision, flags);
+ continue;
+
+
+ case 'n':
+ if (qualifier == 'l') {
+ long * ip = va_arg(args, long *);
+ *ip = (str - buf);
+ } else if (qualifier == 'Z') {
+ size_t * ip = va_arg(args, size_t *);
+ *ip = (str - buf);
+ } else {
+ int * ip = va_arg(args, int *);
+ *ip = (str - buf);
+ }
+ continue;
+
+ case '%':
+ if (str <= end)
+ *str = '%';
+ ++str;
+ continue;
+
+ /* integer number formats - set up the flags and "break" */
+ case 'o':
+ base = 8;
+ break;
+
+ case 'X':
+ flags |= LARGE;
+ case 'x':
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= SIGN;
+ case 'u':
+ break;
+
+ default:
+ if (str <= end)
+ *str = '%';
+ ++str;
+ if (*fmt) {
+ if (str <= end)
+ *str = *fmt;
+ ++str;
+ } else {
+ --fmt;
+ }
+ continue;
+ }
+ if (qualifier == 'L')
+ num = va_arg(args, long long);
+ else if (qualifier == 'l') {
+ num = va_arg(args, unsigned long);
+ if (flags & SIGN)
+ num = (signed long) num;
+ } else if (qualifier == 'Z') {
+ num = va_arg(args, size_t);
+ } else if (qualifier == 'h') {
+ num = (unsigned short) va_arg(args, int);
+ if (flags & SIGN)
+ num = (signed short) num;
+ } else {
+ num = va_arg(args, unsigned int);
+ if (flags & SIGN)
+ num = (signed int) num;
+ }
+
+ str = number(str, end, num, base,
+ field_width, precision, flags);
+ }
+ if (str <= end)
+ *str = '\0';
+ else if (size > 0)
+ /* don't write out a null byte if the buf size is zero */
+ *end = '\0';
+ /* the trailing null byte doesn't count towards the total
+ * ++str;
+ */
+ return str-buf;
+}
+
+/**
+ * snprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ */
+int snprintf(char * buf, size_t size, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsnprintf(buf,size,fmt,args);
+ va_end(args);
+ return i;
+}
+
+/**
+ * vsprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want sprintf instead.
+ */
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ return vsnprintf(buf, 0xFFFFFFFFUL, fmt, args);
+}
+
+
+/**
+ * sprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ */
+int sprintf(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsprintf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
+/**
+ * vsscanf - Unformat a buffer into a list of arguments
+ * @buf: input buffer
+ * @fmt: format of buffer
+ * @args: arguments
+ */
+int vsscanf(const char * buf, const char * fmt, va_list args)
+{
+ const char *str = buf;
+ char *next;
+ char digit;
+ int num = 0;
+ int qualifier;
+ int base;
+ int field_width;
+ int is_sign = 0;
+
+ while(*fmt && *str) {
+ /* skip any white space in format */
+ /* white space in format matchs any amount of
+ * white space, including none, in the input.
+ */
+ if (isspace(*fmt)) {
+ while (isspace(*fmt))
+ ++fmt;
+ while (isspace(*str))
+ ++str;
+ }
+
+ /* anything that is not a conversion must match exactly */
+ if (*fmt != '%' && *fmt) {
+ if (*fmt++ != *str++)
+ break;
+ continue;
+ }
+
+ if (!*fmt)
+ break;
+ ++fmt;
+
+ /* skip this conversion.
+ * advance both strings to next white space
+ */
+ if (*fmt == '*') {
+ while (!isspace(*fmt) && *fmt)
+ fmt++;
+ while (!isspace(*str) && *str)
+ str++;
+ continue;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (isdigit(*fmt))
+ field_width = skip_atoi(&fmt);
+
+ /* get conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
+ *fmt == 'Z' || *fmt == 'z') {
+ qualifier = *fmt++;
+ if (unlikely(qualifier == *fmt)) {
+ if (qualifier == 'h') {
+ qualifier = 'H';
+ fmt++;
+ } else if (qualifier == 'l') {
+ qualifier = 'L';
+ fmt++;
+ }
+ }
+ }
+ base = 10;
+ is_sign = 0;
+
+ if (!*fmt || !*str)
+ break;
+
+ switch(*fmt++) {
+ case 'c':
+ {
+ char *s = (char *) va_arg(args,char*);
+ if (field_width == -1)
+ field_width = 1;
+ do {
+ *s++ = *str++;
+ } while (--field_width > 0 && *str);
+ num++;
+ }
+ continue;
+ case 's':
+ {
+ char *s = (char *) va_arg(args, char *);
+ if(field_width == -1)
+ field_width = INT_MAX;
+ /* first, skip leading white space in buffer */
+ while (isspace(*str))
+ str++;
+
+ /* now copy until next white space */
+ while (*str && !isspace(*str) && field_width--) {
+ *s++ = *str++;
+ }
+ *s = '\0';
+ num++;
+ }
+ continue;
+ case 'n':
+ /* return number of characters read so far */
+ {
+ int *i = (int *)va_arg(args,int*);
+ *i = str - buf;
+ }
+ continue;
+ case 'o':
+ base = 8;
+ break;
+ case 'x':
+ case 'X':
+ base = 16;
+ break;
+ case 'i':
+ base = 0;
+ case 'd':
+ is_sign = 1;
+ case 'u':
+ break;
+ case '%':
+ /* looking for '%' in str */
+ if (*str++ != '%')
+ return num;
+ continue;
+ default:
+ /* invalid format; stop here */
+ return num;
+ }
+
+ /* have some sort of integer conversion.
+ * first, skip white space in buffer.
+ */
+ while (isspace(*str))
+ str++;
+
+ digit = *str;
+ if (is_sign && digit == '-')
+ digit = *(str + 1);
+
+ if (!digit
+ || (base == 16 && !isxdigit(digit))
+ || (base == 10 && !isdigit(digit))
+ || (base == 8 && (!isdigit(digit) || digit > '7'))
+ || (base == 0 && !isdigit(digit)))
+ break;
+
+ switch(qualifier) {
+ case 'H': /* that's 'hh' in format */
+ if (is_sign) {
+ signed char *s = (signed char *) va_arg(args,signed char *);
+ *s = (signed char) simple_strtol(str,&next,base);
+ } else {
+ unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
+ *s = (unsigned char) simple_strtoul(str, &next, base);
+ }
+ break;
+ case 'h':
+ if (is_sign) {
+ short *s = (short *) va_arg(args,short *);
+ *s = (short) simple_strtol(str,&next,base);
+ } else {
+ unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
+ *s = (unsigned short) simple_strtoul(str, &next, base);
+ }
+ break;
+ case 'l':
+ if (is_sign) {
+ long *l = (long *) va_arg(args,long *);
+ *l = simple_strtol(str,&next,base);
+ } else {
+ unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
+ *l = simple_strtoul(str,&next,base);
+ }
+ break;
+ case 'L':
+ if (is_sign) {
+ long long *l = (long long*) va_arg(args,long long *);
+ *l = simple_strtoll(str,&next,base);
+ } else {
+ unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
+ *l = simple_strtoull(str,&next,base);
+ }
+ break;
+ case 'Z':
+ case 'z':
+ {
+ size_t *s = (size_t*) va_arg(args,size_t*);
+ *s = (size_t) simple_strtoul(str,&next,base);
+ }
+ break;
+ default:
+ if (is_sign) {
+ int *i = (int *) va_arg(args, int*);
+ *i = (int) simple_strtol(str,&next,base);
+ } else {
+ unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
+ *i = (unsigned int) simple_strtoul(str,&next,base);
+ }
+ break;
+ }
+ num++;
+
+ if (!next)
+ break;
+ str = next;
+ }
+ return num;
+}
+
+/**
+ * sscanf - Unformat a buffer into a list of arguments
+ * @buf: input buffer
+ * @fmt: formatting of buffer
+ * @...: resulting arguments
+ */
+int sscanf(const char * buf, const char * fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args,fmt);
+ i = vsscanf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
+#endif
--- /dev/null
+#include <mini-os/kernel.h>
+#include <mini-os/console.h>
+
+void __stack_chk_fail(void)
+{
+ printk("stack smashing detected\n");
+ do_exit();
+}
--- /dev/null
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: string.c
+ * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
+ * Changes:
+ *
+ * Date: Aug 2003
+ *
+ * Environment: Xen Minimal OS
+ * Description: Library function for string and memory manipulation
+ * Origin unknown
+ *
+ ****************************************************************************
+ * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
+ ****************************************************************************
+ */
+
+#include <strings.h>
+
+/* newlib defines ffs but not ffsll or ffsl */
+int __ffsti2 (long long int lli)
+{
+ int i, num, t, tmpint, len;
+
+ num = sizeof(long long int) / sizeof(int);
+ if (num == 1) return (ffs((int) lli));
+ len = sizeof(int) * 8;
+
+ for (i = 0; i < num; i++) {
+ tmpint = (int) (((lli >> len) << len) ^ lli);
+
+ t = ffs(tmpint);
+ if (t)
+ return (t + i * len);
+ lli = lli >> len;
+ }
+ return 0;
+}
+
+int __ffsdi2 (long int li)
+{
+ return __ffsti2 ((long long int) li);
+}
+
+int ffsl (long int li)
+{
+ return __ffsti2 ((long long int) li);
+}
+
+int ffsll (long long int lli)
+{
+ return __ffsti2 (lli);
+}
+
+#if !defined HAVE_LIBC
+
+#include <mini-os/os.h>
+#include <mini-os/types.h>
+#include <mini-os/lib.h>
+#include <mini-os/xmalloc.h>
+
+int memcmp(const void * cs,const void * ct,size_t count)
+{
+ const unsigned char *su1, *su2;
+ signed char res = 0;
+
+ for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+ if ((res = *su1 - *su2) != 0)
+ break;
+ return res;
+}
+
+void * memcpy(void * dest,const void *src,size_t count)
+{
+ char *tmp = (char *) dest;
+ const char *s = src;
+
+ while (count--)
+ *tmp++ = *s++;
+
+ return dest;
+}
+
+int strncmp(const char * cs,const char * ct,size_t count)
+{
+ register signed char __res = 0;
+
+ while (count) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ count--;
+ }
+
+ return __res;
+}
+
+int strcmp(const char * cs,const char * ct)
+{
+ register signed char __res;
+
+ while (1) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ }
+
+ return __res;
+}
+
+char * strcpy(char * dest,const char *src)
+{
+ char *tmp = dest;
+
+ while ((*dest++ = *src++) != '\0')
+ /* nothing */;
+ return tmp;
+}
+
+char * strncpy(char * dest,const char *src,size_t count)
+{
+ char *tmp = dest;
+
+ while (count-- && (*dest++ = *src++) != '\0')
+ /* nothing */;
+
+ return tmp;
+}
+
+void * memset(void * s,int c,size_t count)
+{
+ char *xs = (char *) s;
+
+ while (count--)
+ *xs++ = c;
+
+ return s;
+}
+
+size_t strnlen(const char * s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+
+
+char * strcat(char * dest, const char * src)
+{
+ char *tmp = dest;
+
+ while (*dest)
+ dest++;
+
+ while ((*dest++ = *src++) != '\0');
+
+ return tmp;
+}
+
+size_t strlen(const char * s)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+
+char * strchr(const char * s, int c)
+{
+ for(; *s != (char) c; ++s)
+ if (*s == '\0')
+ return NULL;
+ return (char *)s;
+}
+
+char * strrchr(const char * s, int c)
+{
+ const char *res = NULL;
+ for(; *s != '\0'; ++s)
+ if (*s == (char) c)
+ res = s;
+ return (char *)res;
+}
+
+char * strstr(const char * s1,const char * s2)
+{
+ int l1, l2;
+
+ l2 = strlen(s2);
+ if (!l2)
+ return (char *) s1;
+ l1 = strlen(s1);
+ while (l1 >= l2) {
+ l1--;
+ if (!memcmp(s1,s2,l2))
+ return (char *) s1;
+ s1++;
+ }
+ return NULL;
+}
+
+char *strdup(const char *x)
+{
+ int l = strlen(x);
+ char *res = malloc(l + 1);
+ if (!res) return NULL;
+ memcpy(res, x, l + 1);
+ return res;
+}
+
+int ffs(int i)
+{
+ int c = 1;
+
+ do {
+ if (i & 1)
+ return (c);
+ i = i >> 1;
+ c++;
+ } while (i);
+ return 0;
+}
+
+#endif
--- /dev/null
+/*
+ * POSIX-compatible libc layer
+ *
+ * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, October 2007
+ *
+ * Provides the UNIXish part of the standard libc function.
+ *
+ * Relatively straight-forward: just multiplex the file descriptor operations
+ * among the various file types (console, FS, network, ...)
+ */
+
+//#define LIBC_VERBOSE
+//#define LIBC_DEBUG
+
+#ifdef LIBC_DEBUG
+#define DEBUG(fmt,...) printk(fmt, ##__VA_ARGS__)
+#else
+#define DEBUG(fmt,...)
+#endif
+
+#ifdef HAVE_LIBC
+#include <os.h>
+#include <console.h>
+#include <sched.h>
+#include <events.h>
+#include <wait.h>
+#include <netfront.h>
+#include <blkfront.h>
+#include <fbfront.h>
+#include <tpmfront.h>
+#include <tpm_tis.h>
+#include <xenbus.h>
+#include <xenstore.h>
+#include <poll.h>
+
+#include <sys/types.h>
+#include <sys/unistd.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <net/if.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <assert.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef HAVE_LWIP
+#include <lwip/sockets.h>
+#endif
+
+#define debug(fmt, ...) \
+
+#define print_unsupported(fmt, ...) \
+ printk("Unsupported function "fmt" called in Mini-OS kernel\n", ## __VA_ARGS__);
+
+/* Crash on function call */
+#define unsupported_function_crash(function) \
+ int __unsup_##function(void) asm(#function); \
+ int __unsup_##function(void) \
+ { \
+ print_unsupported(#function); \
+ do_exit(); \
+ }
+
+/* Log and err out on function call */
+#define unsupported_function_log(type, function, ret) \
+ type __unsup_##function(void) asm(#function); \
+ type __unsup_##function(void) \
+ { \
+ print_unsupported(#function); \
+ errno = ENOSYS; \
+ return ret; \
+ }
+
+/* Err out on function call */
+#define unsupported_function(type, function, ret) \
+ type __unsup_##function(void) asm(#function); \
+ type __unsup_##function(void) \
+ { \
+ errno = ENOSYS; \
+ return ret; \
+ }
+
+#define NOFILE 32
+extern void minios_interface_close_fd(int fd);
+extern void minios_evtchn_close_fd(int fd);
+extern void minios_gnttab_close_fd(int fd);
+
+pthread_mutex_t fd_lock = PTHREAD_MUTEX_INITIALIZER;
+struct file files[NOFILE] = {
+ { .type = FTYPE_CONSOLE }, /* stdin */
+ { .type = FTYPE_CONSOLE }, /* stdout */
+ { .type = FTYPE_CONSOLE }, /* stderr */
+};
+
+DECLARE_WAIT_QUEUE_HEAD(event_queue);
+
+int alloc_fd(enum fd_type type)
+{
+ int i;
+ pthread_mutex_lock(&fd_lock);
+ for (i=0; i<NOFILE; i++) {
+ if (files[i].type == FTYPE_NONE) {
+ files[i].type = type;
+ pthread_mutex_unlock(&fd_lock);
+ return i;
+ }
+ }
+ pthread_mutex_unlock(&fd_lock);
+ printk("Too many opened files\n");
+ do_exit();
+}
+
+void close_all_files(void)
+{
+ int i;
+ pthread_mutex_lock(&fd_lock);
+ for (i=NOFILE - 1; i > 0; i--)
+ if (files[i].type != FTYPE_NONE)
+ close(i);
+ pthread_mutex_unlock(&fd_lock);
+}
+
+int dup2(int oldfd, int newfd)
+{
+ pthread_mutex_lock(&fd_lock);
+ if (files[newfd].type != FTYPE_NONE)
+ close(newfd);
+ // XXX: this is a bit bogus, as we are supposed to share the offset etc
+ files[newfd] = files[oldfd];
+ pthread_mutex_unlock(&fd_lock);
+ return 0;
+}
+
+pid_t getpid(void)
+{
+ return 1;
+}
+
+pid_t getppid(void)
+{
+ return 1;
+}
+
+pid_t setsid(void)
+{
+ return 1;
+}
+
+char *getcwd(char *buf, size_t size)
+{
+ snprintf(buf, size, "/");
+ return buf;
+}
+
+#define LOG_PATH "/var/log/"
+#define SAVE_PATH "/var/lib/xen"
+#define SAVE_CONSOLE 1
+#define RESTORE_CONSOLE 2
+
+int mkdir(const char *pathname, mode_t mode)
+{
+ errno = EIO;
+ return -1;
+}
+
+#ifdef CONFIG_CONSFRONT
+int posix_openpt(int flags)
+{
+ struct consfront_dev *dev;
+
+ /* Ignore flags */
+
+ dev = init_consfront(NULL);
+ dev->fd = alloc_fd(FTYPE_CONSOLE);
+ files[dev->fd].cons.dev = dev;
+
+ printk("fd(%d) = posix_openpt\n", dev->fd);
+ return(dev->fd);
+}
+
+int open_savefile(const char *path, int save)
+{
+ struct consfront_dev *dev;
+ char nodename[64];
+
+ snprintf(nodename, sizeof(nodename), "device/console/%d", save ? SAVE_CONSOLE : RESTORE_CONSOLE);
+
+ dev = init_consfront(nodename);
+ dev->fd = alloc_fd(FTYPE_SAVEFILE);
+ files[dev->fd].cons.dev = dev;
+
+ printk("fd(%d) = open_savefile\n", dev->fd);
+ return(dev->fd);
+}
+#else
+int posix_openpt(int flags)
+{
+ errno = EIO;
+ return -1;
+}
+int open_savefile(const char *path, int save)
+{
+ errno = EIO;
+ return -1;
+}
+#endif
+
+int open(const char *pathname, int flags, ...)
+{
+ int fd;
+ /* Ugly, but fine. */
+ if (!strncmp(pathname,LOG_PATH,strlen(LOG_PATH))) {
+ fd = alloc_fd(FTYPE_CONSOLE);
+ printk("open(%s) -> %d\n", pathname, fd);
+ return fd;
+ }
+ if (!strncmp(pathname, "/dev/mem", strlen("/dev/mem"))) {
+ fd = alloc_fd(FTYPE_MEM);
+ printk("open(/dev/mem) -> %d\n", fd);
+ return fd;
+ }
+ if (!strncmp(pathname, "/dev/ptmx", strlen("/dev/ptmx")))
+ return posix_openpt(flags);
+ if (!strncmp(pathname,SAVE_PATH,strlen(SAVE_PATH)))
+ return open_savefile(pathname, flags & O_WRONLY);
+ errno = EIO;
+ return -1;
+}
+
+int isatty(int fd)
+{
+ return files[fd].type == FTYPE_CONSOLE;
+}
+
+int read(int fd, void *buf, size_t nbytes)
+{
+ switch (files[fd].type) {
+ case FTYPE_SAVEFILE:
+ case FTYPE_CONSOLE: {
+ int ret;
+ DEFINE_WAIT(w);
+ while(1) {
+ add_waiter(w, console_queue);
+ ret = xencons_ring_recv(files[fd].cons.dev, buf, nbytes);
+ if (ret)
+ break;
+ schedule();
+ }
+ remove_waiter(w, console_queue);
+ return ret;
+ }
+#ifdef HAVE_LWIP
+ case FTYPE_SOCKET:
+ return lwip_read(files[fd].socket.fd, buf, nbytes);
+#endif
+#ifdef CONFIG_NETFRONT
+ case FTYPE_TAP: {
+ ssize_t ret;
+ ret = netfront_receive(files[fd].tap.dev, buf, nbytes);
+ if (ret <= 0) {
+ errno = EAGAIN;
+ return -1;
+ }
+ return ret;
+ }
+#endif
+#ifdef CONFIG_KBDFRONT
+ case FTYPE_KBD: {
+ int ret, n;
+ n = nbytes / sizeof(union xenkbd_in_event);
+ ret = kbdfront_receive(files[fd].kbd.dev, buf, n);
+ if (ret <= 0) {
+ errno = EAGAIN;
+ return -1;
+ }
+ return ret * sizeof(union xenkbd_in_event);
+ }
+#endif
+#ifdef CONFIG_FBFRONT
+ case FTYPE_FB: {
+ int ret, n;
+ n = nbytes / sizeof(union xenfb_in_event);
+ ret = fbfront_receive(files[fd].fb.dev, buf, n);
+ if (ret <= 0) {
+ errno = EAGAIN;
+ return -1;
+ }
+ return ret * sizeof(union xenfb_in_event);
+ }
+#endif
+#ifdef CONFIG_BLKFRONT
+ case FTYPE_BLK: {
+ return blkfront_posix_read(fd, buf, nbytes);
+ }
+#endif
+#ifdef CONFIG_TPMFRONT
+ case FTYPE_TPMFRONT: {
+ return tpmfront_posix_read(fd, buf, nbytes);
+ }
+#endif
+#ifdef CONFIG_TPM_TIS
+ case FTYPE_TPM_TIS: {
+ return tpm_tis_posix_read(fd, buf, nbytes);
+ }
+#endif
+ default:
+ break;
+ }
+ printk("read(%d): Bad descriptor\n", fd);
+ errno = EBADF;
+ return -1;
+}
+
+int write(int fd, const void *buf, size_t nbytes)
+{
+ switch (files[fd].type) {
+ case FTYPE_SAVEFILE: {
+ int ret = 0, tot = nbytes;
+ while (nbytes > 0) {
+ ret = xencons_ring_send(files[fd].cons.dev, (char *)buf, nbytes);
+ nbytes -= ret;
+ buf = (char *)buf + ret;
+ }
+ return tot - nbytes;
+ }
+ case FTYPE_CONSOLE:
+ console_print(files[fd].cons.dev, (char *)buf, nbytes);
+ return nbytes;
+#ifdef HAVE_LWIP
+ case FTYPE_SOCKET:
+ return lwip_write(files[fd].socket.fd, (void*) buf, nbytes);
+#endif
+#ifdef CONFIG_NETFRONT
+ case FTYPE_TAP:
+ netfront_xmit(files[fd].tap.dev, (void*) buf, nbytes);
+ return nbytes;
+#endif
+#ifdef CONFIG_BLKFRONT
+ case FTYPE_BLK:
+ return blkfront_posix_write(fd, buf, nbytes);
+#endif
+#ifdef CONFIG_TPMFRONT
+ case FTYPE_TPMFRONT:
+ return tpmfront_posix_write(fd, buf, nbytes);
+#endif
+#ifdef CONFIG_TPM_TIS
+ case FTYPE_TPM_TIS:
+ return tpm_tis_posix_write(fd, buf, nbytes);
+#endif
+ default:
+ break;
+ }
+ printk("write(%d): Bad descriptor\n", fd);
+ errno = EBADF;
+ return -1;
+}
+
+off_t lseek(int fd, off_t offset, int whence)
+{
+ off_t* target = NULL;
+ switch(files[fd].type) {
+#ifdef CONFIG_BLKFRONT
+ case FTYPE_BLK:
+ target = &files[fd].blk.offset;
+ break;
+#endif
+#ifdef CONFIG_TPMFRONT
+ case FTYPE_TPMFRONT:
+ target = &files[fd].tpmfront.offset;
+ break;
+#endif
+#ifdef CONFIG_TPM_TIS
+ case FTYPE_TPM_TIS:
+ target = &files[fd].tpm_tis.offset;
+ break;
+#endif
+ case FTYPE_FILE:
+ target = &files[fd].file.offset;
+ break;
+ default:
+ /* Not implemented for this filetype */
+ errno = ESPIPE;
+ return (off_t) -1;
+ }
+
+ switch (whence) {
+ case SEEK_SET:
+ *target = offset;
+ break;
+ case SEEK_CUR:
+ *target += offset;
+ break;
+ case SEEK_END:
+ {
+ struct stat st;
+ int ret;
+ ret = fstat(fd, &st);
+ if (ret)
+ return -1;
+ *target = st.st_size + offset;
+ break;
+ }
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+ return *target;
+}
+
+int fsync(int fd) {
+ errno = EBADF;
+ return -1;
+}
+
+int close(int fd)
+{
+ printk("close(%d)\n", fd);
+ switch (files[fd].type) {
+ default:
+ files[fd].type = FTYPE_NONE;
+ return 0;
+#ifdef CONFIG_XENBUS
+ case FTYPE_XENBUS:
+ xs_daemon_close((void*)(intptr_t) fd);
+ return 0;
+#endif
+#ifdef HAVE_LWIP
+ case FTYPE_SOCKET: {
+ int res = lwip_close(files[fd].socket.fd);
+ files[fd].type = FTYPE_NONE;
+ return res;
+ }
+#endif
+#ifdef CONFIG_XC
+ case FTYPE_XC:
+ minios_interface_close_fd(fd);
+ return 0;
+ case FTYPE_EVTCHN:
+ minios_evtchn_close_fd(fd);
+ return 0;
+ case FTYPE_GNTMAP:
+ minios_gnttab_close_fd(fd);
+ return 0;
+#endif
+#ifdef CONFIG_NETFRONT
+ case FTYPE_TAP:
+ shutdown_netfront(files[fd].tap.dev);
+ files[fd].type = FTYPE_NONE;
+ return 0;
+#endif
+#ifdef CONFIG_BLKFRONT
+ case FTYPE_BLK:
+ shutdown_blkfront(files[fd].blk.dev);
+ files[fd].type = FTYPE_NONE;
+ return 0;
+#endif
+#ifdef CONFIG_TPMFRONT
+ case FTYPE_TPMFRONT:
+ shutdown_tpmfront(files[fd].tpmfront.dev);
+ files[fd].type = FTYPE_NONE;
+ return 0;
+#endif
+#ifdef CONFIG_TPM_TIS
+ case FTYPE_TPM_TIS:
+ shutdown_tpm_tis(files[fd].tpm_tis.dev);
+ files[fd].type = FTYPE_NONE;
+ return 0;
+#endif
+#ifdef CONFIG_KBDFRONT
+ case FTYPE_KBD:
+ shutdown_kbdfront(files[fd].kbd.dev);
+ files[fd].type = FTYPE_NONE;
+ return 0;
+#endif
+#ifdef CONFIG_FBFRONT
+ case FTYPE_FB:
+ shutdown_fbfront(files[fd].fb.dev);
+ files[fd].type = FTYPE_NONE;
+ return 0;
+#endif
+#ifdef CONFIG_CONSFRONT
+ case FTYPE_SAVEFILE:
+ case FTYPE_CONSOLE:
+ fini_console(files[fd].cons.dev);
+ files[fd].type = FTYPE_NONE;
+ return 0;
+#endif
+ case FTYPE_NONE:
+ break;
+ }
+ printk("close(%d): Bad descriptor\n", fd);
+ errno = EBADF;
+ return -1;
+}
+
+static void init_stat(struct stat *buf)
+{
+ memset(buf, 0, sizeof(*buf));
+ buf->st_dev = 0;
+ buf->st_ino = 0;
+ buf->st_nlink = 1;
+ buf->st_rdev = 0;
+ buf->st_blksize = 4096;
+ buf->st_blocks = 0;
+}
+
+int stat(const char *path, struct stat *buf)
+{
+ errno = EIO;
+ return -1;
+}
+
+int fstat(int fd, struct stat *buf)
+{
+ init_stat(buf);
+ switch (files[fd].type) {
+ case FTYPE_SAVEFILE:
+ case FTYPE_CONSOLE:
+ case FTYPE_SOCKET: {
+ if (files[fd].type == FTYPE_CONSOLE)
+ buf->st_mode = S_IFCHR|S_IRUSR|S_IWUSR;
+ else if (files[fd].type == FTYPE_SOCKET)
+ buf->st_mode = S_IFSOCK|S_IRUSR|S_IWUSR;
+ else if (files[fd].type == FTYPE_SAVEFILE)
+ buf->st_mode = S_IFREG|S_IRUSR|S_IWUSR;
+ buf->st_uid = 0;
+ buf->st_gid = 0;
+ buf->st_size = 0;
+ buf->st_atime =
+ buf->st_mtime =
+ buf->st_ctime = time(NULL);
+ return 0;
+ }
+#ifdef CONFIG_BLKFRONT
+ case FTYPE_BLK:
+ return blkfront_posix_fstat(fd, buf);
+#endif
+#ifdef CONFIG_TPMFRONT
+ case FTYPE_TPMFRONT:
+ return tpmfront_posix_fstat(fd, buf);
+#endif
+#ifdef CONFIG_TPM_TIS
+ case FTYPE_TPM_TIS:
+ return tpm_tis_posix_fstat(fd, buf);
+#endif
+ default:
+ break;
+ }
+
+ printk("statf(%d): Bad descriptor\n", fd);
+ errno = EBADF;
+ return -1;
+}
+
+int ftruncate(int fd, off_t length)
+{
+ errno = EBADF;
+ return -1;
+}
+
+int remove(const char *pathname)
+{
+ errno = EIO;
+ return -1;
+}
+
+int unlink(const char *pathname)
+{
+ return remove(pathname);
+}
+
+int rmdir(const char *pathname)
+{
+ return remove(pathname);
+}
+
+int fcntl(int fd, int cmd, ...)
+{
+ long arg;
+ va_list ap;
+ va_start(ap, cmd);
+ arg = va_arg(ap, long);
+ va_end(ap);
+
+ switch (cmd) {
+#ifdef HAVE_LWIP
+ case F_SETFL:
+ if (files[fd].type == FTYPE_SOCKET && !(arg & ~O_NONBLOCK)) {
+ /* Only flag supported: non-blocking mode */
+ uint32_t nblock = !!(arg & O_NONBLOCK);
+ return lwip_ioctl(files[fd].socket.fd, FIONBIO, &nblock);
+ }
+ /* Fallthrough */
+#endif
+ default:
+ printk("fcntl(%d, %d, %lx/%lo)\n", fd, cmd, arg, arg);
+ errno = ENOSYS;
+ return -1;
+ }
+}
+
+DIR *opendir(const char *name)
+{
+ DIR *ret;
+ ret = malloc(sizeof(*ret));
+ ret->name = strdup(name);
+ ret->offset = 0;
+ ret->entries = NULL;
+ ret->curentry = -1;
+ ret->nbentries = 0;
+ ret->has_more = 1;
+ return ret;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+ return NULL;
+}
+
+int closedir(DIR *dir)
+{
+ int i;
+ for (i=0; i<dir->nbentries; i++)
+ free(dir->entries[i]);
+ free(dir->entries);
+ free(dir->name);
+ free(dir);
+ return 0;
+}
+
+/* We assume that only the main thread calls select(). */
+
+static const char file_types[] = {
+ [FTYPE_NONE] = 'N',
+ [FTYPE_CONSOLE] = 'C',
+ [FTYPE_XENBUS] = 'S',
+ [FTYPE_XC] = 'X',
+ [FTYPE_EVTCHN] = 'E',
+ [FTYPE_SOCKET] = 's',
+ [FTYPE_TAP] = 'T',
+ [FTYPE_BLK] = 'B',
+ [FTYPE_KBD] = 'K',
+ [FTYPE_FB] = 'G',
+};
+#ifdef LIBC_DEBUG
+static void dump_set(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
+{
+ int i, comma;
+#define printfds(set) do {\
+ comma = 0; \
+ for (i = 0; i < nfds; i++) { \
+ if (FD_ISSET(i, set)) { \
+ if (comma) \
+ printk(", "); \
+ printk("%d(%c)", i, file_types[files[i].type]); \
+ comma = 1; \
+ } \
+ } \
+} while (0)
+
+ printk("[");
+ if (readfds)
+ printfds(readfds);
+ printk("], [");
+ if (writefds)
+ printfds(writefds);
+ printk("], [");
+ if (exceptfds)
+ printfds(exceptfds);
+ printk("], ");
+ if (timeout)
+ printk("{ %ld, %ld }", timeout->tv_sec, timeout->tv_usec);
+}
+#else
+#define dump_set(nfds, readfds, writefds, exceptfds, timeout)
+#endif
+
+#ifdef LIBC_DEBUG
+static void dump_pollfds(struct pollfd *pfd, int nfds, int timeout)
+{
+ int i, comma, fd;
+
+ printk("[");
+ comma = 0;
+ for (i = 0; i < nfds; i++) {
+ fd = pfd[i].fd;
+ if (comma)
+ printk(", ");
+ printk("%d(%c)/%02x", fd, file_types[files[fd].type],
+ pfd[i].events);
+ comma = 1;
+ }
+ printk("]");
+
+ printk(", %d, %d", nfds, timeout);
+}
+#else
+#define dump_pollfds(pfds, nfds, timeout)
+#endif
+
+/* Just poll without blocking */
+static int select_poll(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
+{
+ int i, n = 0;
+#ifdef HAVE_LWIP
+ int sock_n = 0, sock_nfds = 0;
+ fd_set sock_readfds, sock_writefds, sock_exceptfds;
+ struct timeval timeout = { .tv_sec = 0, .tv_usec = 0};
+#endif
+
+#ifdef LIBC_VERBOSE
+ static int nb;
+ static int nbread[NOFILE], nbwrite[NOFILE], nbexcept[NOFILE];
+ static s_time_t lastshown;
+
+ nb++;
+#endif
+
+#ifdef HAVE_LWIP
+ /* first poll network */
+ FD_ZERO(&sock_readfds);
+ FD_ZERO(&sock_writefds);
+ FD_ZERO(&sock_exceptfds);
+ for (i = 0; i < nfds; i++) {
+ if (files[i].type == FTYPE_SOCKET) {
+ if (FD_ISSET(i, readfds)) {
+ FD_SET(files[i].socket.fd, &sock_readfds);
+ sock_nfds = i+1;
+ }
+ if (FD_ISSET(i, writefds)) {
+ FD_SET(files[i].socket.fd, &sock_writefds);
+ sock_nfds = i+1;
+ }
+ if (FD_ISSET(i, exceptfds)) {
+ FD_SET(files[i].socket.fd, &sock_exceptfds);
+ sock_nfds = i+1;
+ }
+ }
+ }
+ if (sock_nfds > 0) {
+ DEBUG("lwip_select(");
+ dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
+ DEBUG("); -> ");
+ sock_n = lwip_select(sock_nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
+ dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
+ DEBUG("\n");
+ }
+#endif
+
+ /* Then see others as well. */
+ for (i = 0; i < nfds; i++) {
+ switch(files[i].type) {
+ default:
+ if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
+ printk("bogus fd %d in select\n", i);
+ /* Fallthrough. */
+ case FTYPE_CONSOLE:
+ if (FD_ISSET(i, readfds)) {
+ if (xencons_ring_avail(files[i].cons.dev))
+ n++;
+ else
+ FD_CLR(i, readfds);
+ }
+ if (FD_ISSET(i, writefds))
+ n++;
+ FD_CLR(i, exceptfds);
+ break;
+#ifdef CONFIG_XENBUS
+ case FTYPE_XENBUS:
+ if (FD_ISSET(i, readfds)) {
+ if (files[i].xenbus.events)
+ n++;
+ else
+ FD_CLR(i, readfds);
+ }
+ FD_CLR(i, writefds);
+ FD_CLR(i, exceptfds);
+ break;
+#endif
+ case FTYPE_EVTCHN:
+ case FTYPE_TAP:
+ case FTYPE_BLK:
+ case FTYPE_KBD:
+ case FTYPE_FB:
+ if (FD_ISSET(i, readfds)) {
+ if (files[i].read)
+ n++;
+ else
+ FD_CLR(i, readfds);
+ }
+ FD_CLR(i, writefds);
+ FD_CLR(i, exceptfds);
+ break;
+#ifdef HAVE_LWIP
+ case FTYPE_SOCKET:
+ if (FD_ISSET(i, readfds)) {
+ /* Optimize no-network-packet case. */
+ if (sock_n && FD_ISSET(files[i].socket.fd, &sock_readfds))
+ n++;
+ else
+ FD_CLR(i, readfds);
+ }
+ if (FD_ISSET(i, writefds)) {
+ if (sock_n && FD_ISSET(files[i].socket.fd, &sock_writefds))
+ n++;
+ else
+ FD_CLR(i, writefds);
+ }
+ if (FD_ISSET(i, exceptfds)) {
+ if (sock_n && FD_ISSET(files[i].socket.fd, &sock_exceptfds))
+ n++;
+ else
+ FD_CLR(i, exceptfds);
+ }
+ break;
+#endif
+ }
+#ifdef LIBC_VERBOSE
+ if (FD_ISSET(i, readfds))
+ nbread[i]++;
+ if (FD_ISSET(i, writefds))
+ nbwrite[i]++;
+ if (FD_ISSET(i, exceptfds))
+ nbexcept[i]++;
+#endif
+ }
+#ifdef LIBC_VERBOSE
+ if (NOW() > lastshown + 1000000000ull) {
+ lastshown = NOW();
+ printk("%lu MB free, ", num_free_pages() / ((1 << 20) / PAGE_SIZE));
+ printk("%d(%d): ", nb, sock_n);
+ for (i = 0; i < nfds; i++) {
+ if (nbread[i] || nbwrite[i] || nbexcept[i])
+ printk(" %d(%c):", i, file_types[files[i].type]);
+ if (nbread[i])
+ printk(" %dR", nbread[i]);
+ if (nbwrite[i])
+ printk(" %dW", nbwrite[i]);
+ if (nbexcept[i])
+ printk(" %dE", nbexcept[i]);
+ }
+ printk("\n");
+ memset(nbread, 0, sizeof(nbread));
+ memset(nbwrite, 0, sizeof(nbwrite));
+ memset(nbexcept, 0, sizeof(nbexcept));
+ nb = 0;
+ }
+#endif
+ return n;
+}
+
+/* The strategy is to
+ * - announce that we will maybe sleep
+ * - poll a bit ; if successful, return
+ * - if timeout, return
+ * - really sleep (except if somebody woke us in the meanwhile) */
+int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ struct timeval *timeout)
+{
+ int n, ret;
+ fd_set myread, mywrite, myexcept;
+ struct thread *thread = get_current();
+ s_time_t start = NOW(), stop;
+#ifdef CONFIG_NETFRONT
+ DEFINE_WAIT(netfront_w);
+#endif
+ DEFINE_WAIT(event_w);
+#ifdef CONFIG_BLKFRONT
+ DEFINE_WAIT(blkfront_w);
+#endif
+#ifdef CONFIG_XENBUS
+ DEFINE_WAIT(xenbus_watch_w);
+#endif
+#ifdef CONFIG_KBDFRONT
+ DEFINE_WAIT(kbdfront_w);
+#endif
+ DEFINE_WAIT(console_w);
+
+ assert(thread == main_thread);
+
+ DEBUG("select(%d, ", nfds);
+ dump_set(nfds, readfds, writefds, exceptfds, timeout);
+ DEBUG(");\n");
+
+ if (timeout)
+ stop = start + SECONDS(timeout->tv_sec) + timeout->tv_usec * 1000;
+ else
+ /* just make gcc happy */
+ stop = start;
+
+ /* Tell people we're going to sleep before looking at what they are
+ * saying, hence letting them wake us if events happen between here and
+ * schedule() */
+#ifdef CONFIG_NETFRONT
+ add_waiter(netfront_w, netfront_queue);
+#endif
+ add_waiter(event_w, event_queue);
+#ifdef CONFIG_BLKFRONT
+ add_waiter(blkfront_w, blkfront_queue);
+#endif
+#ifdef CONFIG_XENBUS
+ add_waiter(xenbus_watch_w, xenbus_watch_queue);
+#endif
+#ifdef CONFIG_KBDFRONT
+ add_waiter(kbdfront_w, kbdfront_queue);
+#endif
+ add_waiter(console_w, console_queue);
+
+ if (readfds)
+ myread = *readfds;
+ else
+ FD_ZERO(&myread);
+ if (writefds)
+ mywrite = *writefds;
+ else
+ FD_ZERO(&mywrite);
+ if (exceptfds)
+ myexcept = *exceptfds;
+ else
+ FD_ZERO(&myexcept);
+
+ DEBUG("polling ");
+ dump_set(nfds, &myread, &mywrite, &myexcept, timeout);
+ DEBUG("\n");
+ n = select_poll(nfds, &myread, &mywrite, &myexcept);
+
+ if (n) {
+ dump_set(nfds, readfds, writefds, exceptfds, timeout);
+ if (readfds)
+ *readfds = myread;
+ if (writefds)
+ *writefds = mywrite;
+ if (exceptfds)
+ *exceptfds = myexcept;
+ DEBUG(" -> ");
+ dump_set(nfds, readfds, writefds, exceptfds, timeout);
+ DEBUG("\n");
+ wake(thread);
+ ret = n;
+ goto out;
+ }
+ if (timeout && NOW() >= stop) {
+ if (readfds)
+ FD_ZERO(readfds);
+ if (writefds)
+ FD_ZERO(writefds);
+ if (exceptfds)
+ FD_ZERO(exceptfds);
+ timeout->tv_sec = 0;
+ timeout->tv_usec = 0;
+ wake(thread);
+ ret = 0;
+ goto out;
+ }
+
+ if (timeout)
+ thread->wakeup_time = stop;
+ schedule();
+
+ if (readfds)
+ myread = *readfds;
+ else
+ FD_ZERO(&myread);
+ if (writefds)
+ mywrite = *writefds;
+ else
+ FD_ZERO(&mywrite);
+ if (exceptfds)
+ myexcept = *exceptfds;
+ else
+ FD_ZERO(&myexcept);
+
+ n = select_poll(nfds, &myread, &mywrite, &myexcept);
+
+ if (n) {
+ if (readfds)
+ *readfds = myread;
+ if (writefds)
+ *writefds = mywrite;
+ if (exceptfds)
+ *exceptfds = myexcept;
+ ret = n;
+ goto out;
+ }
+ errno = EINTR;
+ ret = -1;
+
+out:
+#ifdef CONFIG_NETFRONT
+ remove_waiter(netfront_w, netfront_queue);
+#endif
+ remove_waiter(event_w, event_queue);
+#ifdef CONFIG_BLKFRONT
+ remove_waiter(blkfront_w, blkfront_queue);
+#endif
+#ifdef CONFIG_XENBUS
+ remove_waiter(xenbus_watch_w, xenbus_watch_queue);
+#endif
+#ifdef CONFIG_KBDFRONT
+ remove_waiter(kbdfront_w, kbdfront_queue);
+#endif
+ remove_waiter(console_w, console_queue);
+ return ret;
+}
+
+/* Wrap around select */
+int poll(struct pollfd _pfd[], nfds_t _nfds, int _timeout)
+{
+ int n, ret;
+ int i, fd;
+ struct timeval _timeo, *timeo = NULL;
+ fd_set rfds, wfds, efds;
+ int max_fd = -1;
+
+ DEBUG("poll(");
+ dump_pollfds(_pfd, _nfds, _timeout);
+ DEBUG(")\n");
+
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ FD_ZERO(&efds);
+
+ n = 0;
+
+ for (i = 0; i < _nfds; i++) {
+ fd = _pfd[i].fd;
+ _pfd[i].revents = 0;
+
+ /* fd < 0, revents = 0, which is already set */
+ if (fd < 0) continue;
+
+ /* fd is invalid, revents = POLLNVAL, increment counter */
+ if (fd >= NOFILE || files[fd].type == FTYPE_NONE) {
+ n++;
+ _pfd[i].revents |= POLLNVAL;
+ continue;
+ }
+
+ /* normal case, map POLL* into readfds and writefds:
+ * POLLIN -> readfds
+ * POLLOUT -> writefds
+ * POLL* -> none
+ */
+ if (_pfd[i].events & POLLIN)
+ FD_SET(fd, &rfds);
+ if (_pfd[i].events & POLLOUT)
+ FD_SET(fd, &wfds);
+ /* always set exceptfds */
+ FD_SET(fd, &efds);
+ if (fd > max_fd)
+ max_fd = fd;
+ }
+
+ /* should never sleep when we already have events */
+ if (n) {
+ _timeo.tv_sec = 0;
+ _timeo.tv_usec = 0;
+ timeo = &_timeo;
+ } else if (_timeout >= 0) {
+ /* normal case, construct _timeout, might sleep */
+ _timeo.tv_sec = _timeout / 1000;
+ _timeo.tv_usec = (_timeout % 1000) * 1000;
+ timeo = &_timeo;
+ } else {
+ /* _timeout < 0, block forever */
+ timeo = NULL;
+ }
+
+
+ ret = select(max_fd+1, &rfds, &wfds, &efds, timeo);
+ /* error in select, just return, errno is set by select() */
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < _nfds; i++) {
+ fd = _pfd[i].fd;
+
+ /* the revents has already been set for all error case */
+ if (fd < 0 || fd >= NOFILE || files[fd].type == FTYPE_NONE)
+ continue;
+
+ if (FD_ISSET(fd, &rfds) || FD_ISSET(fd, &wfds) || FD_ISSET(fd, &efds))
+ n++;
+ if (FD_ISSET(fd, &efds)) {
+ /* anything bad happens we set POLLERR */
+ _pfd[i].revents |= POLLERR;
+ continue;
+ }
+ if (FD_ISSET(fd, &rfds))
+ _pfd[i].revents |= POLLIN;
+ if (FD_ISSET(fd, &wfds))
+ _pfd[i].revents |= POLLOUT;
+ }
+
+ return n;
+}
+
+#ifdef HAVE_LWIP
+int socket(int domain, int type, int protocol)
+{
+ int fd, res;
+ fd = lwip_socket(domain, type, protocol);
+ if (fd < 0)
+ return -1;
+ res = alloc_fd(FTYPE_SOCKET);
+ printk("socket -> %d\n", res);
+ files[res].socket.fd = fd;
+ return res;
+}
+
+int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+ int fd, res;
+ if (files[s].type != FTYPE_SOCKET) {
+ printk("accept(%d): Bad descriptor\n", s);
+ errno = EBADF;
+ return -1;
+ }
+ fd = lwip_accept(files[s].socket.fd, addr, addrlen);
+ if (fd < 0)
+ return -1;
+ res = alloc_fd(FTYPE_SOCKET);
+ files[res].socket.fd = fd;
+ printk("accepted on %d -> %d\n", s, res);
+ return res;
+}
+
+#define LWIP_STUB(ret, name, proto, args) \
+ret name proto \
+{ \
+ if (files[s].type != FTYPE_SOCKET) { \
+ printk(#name "(%d): Bad descriptor\n", s); \
+ errno = EBADF; \
+ return -1; \
+ } \
+ s = files[s].socket.fd; \
+ return lwip_##name args; \
+}
+
+LWIP_STUB(int, bind, (int s, struct sockaddr *my_addr, socklen_t addrlen), (s, my_addr, addrlen))
+LWIP_STUB(int, getsockopt, (int s, int level, int optname, void *optval, socklen_t *optlen), (s, level, optname, optval, optlen))
+LWIP_STUB(int, setsockopt, (int s, int level, int optname, void *optval, socklen_t optlen), (s, level, optname, optval, optlen))
+LWIP_STUB(int, connect, (int s, struct sockaddr *serv_addr, socklen_t addrlen), (s, serv_addr, addrlen))
+LWIP_STUB(int, listen, (int s, int backlog), (s, backlog));
+LWIP_STUB(ssize_t, recv, (int s, void *buf, size_t len, int flags), (s, buf, len, flags))
+LWIP_STUB(ssize_t, recvfrom, (int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen), (s, buf, len, flags, from, fromlen))
+LWIP_STUB(ssize_t, send, (int s, void *buf, size_t len, int flags), (s, buf, len, flags))
+LWIP_STUB(ssize_t, sendto, (int s, void *buf, size_t len, int flags, struct sockaddr *to, socklen_t tolen), (s, buf, len, flags, to, tolen))
+LWIP_STUB(int, getsockname, (int s, struct sockaddr *name, socklen_t *namelen), (s, name, namelen))
+#endif
+
+static char *syslog_ident;
+void openlog(const char *ident, int option, int facility)
+{
+ free(syslog_ident);
+ syslog_ident = strdup(ident);
+}
+
+void vsyslog(int priority, const char *format, va_list ap)
+{
+ printk("%s: ", syslog_ident);
+ print(0, format, ap);
+}
+
+void syslog(int priority, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vsyslog(priority, format, ap);
+ va_end(ap);
+}
+
+void closelog(void)
+{
+ free(syslog_ident);
+ syslog_ident = NULL;
+}
+
+void vwarn(const char *format, va_list ap)
+{
+ int the_errno = errno;
+ printk("stubdom: ");
+ if (format) {
+ print(0, format, ap);
+ printk(", ");
+ }
+ printk("%s", strerror(the_errno));
+}
+
+void warn(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vwarn(format, ap);
+ va_end(ap);
+}
+
+void verr(int eval, const char *format, va_list ap)
+{
+ vwarn(format, ap);
+ exit(eval);
+}
+
+void err(int eval, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ verr(eval, format, ap);
+ va_end(ap);
+}
+
+void vwarnx(const char *format, va_list ap)
+{
+ printk("stubdom: ");
+ if (format)
+ print(0, format, ap);
+}
+
+void warnx(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vwarnx(format, ap);
+ va_end(ap);
+}
+
+void verrx(int eval, const char *format, va_list ap)
+{
+ vwarnx(format, ap);
+ exit(eval);
+}
+
+void errx(int eval, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ verrx(eval, format, ap);
+ va_end(ap);
+}
+
+int nanosleep(const struct timespec *req, struct timespec *rem)
+{
+ s_time_t start = NOW();
+ s_time_t stop = start + SECONDS(req->tv_sec) + req->tv_nsec;
+ s_time_t stopped;
+ struct thread *thread = get_current();
+
+ thread->wakeup_time = stop;
+ clear_runnable(thread);
+ schedule();
+ stopped = NOW();
+
+ if (rem)
+ {
+ s_time_t remaining = stop - stopped;
+ if (remaining > 0)
+ {
+ rem->tv_nsec = remaining % 1000000000ULL;
+ rem->tv_sec = remaining / 1000000000ULL;
+ } else memset(rem, 0, sizeof(*rem));
+ }
+
+ return 0;
+}
+
+int usleep(useconds_t usec)
+{
+ /* "usec shall be less than one million." */
+ struct timespec req;
+ req.tv_nsec = usec * 1000;
+ req.tv_sec = 0;
+
+ if (nanosleep(&req, NULL))
+ return -1;
+
+ return 0;
+}
+
+unsigned int sleep(unsigned int seconds)
+{
+ struct timespec req, rem;
+ req.tv_sec = seconds;
+ req.tv_nsec = 0;
+
+ if (nanosleep(&req, &rem))
+ return -1;
+
+ if (rem.tv_nsec > 0)
+ rem.tv_sec++;
+
+ return rem.tv_sec;
+}
+
+int clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+ switch (clk_id) {
+ case CLOCK_MONOTONIC:
+ {
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = tv.tv_usec * 1000;
+
+ break;
+ }
+ case CLOCK_REALTIME:
+ {
+ uint64_t nsec = monotonic_clock();
+
+ tp->tv_sec = nsec / 1000000000ULL;
+ tp->tv_nsec = nsec % 1000000000ULL;
+
+ break;
+ }
+ default:
+ print_unsupported("clock_gettime(%d)", clk_id);
+ errno = EINVAL;
+ return -1;
+ }
+
+ return 0;
+}
+
+uid_t getuid(void)
+{
+ return 0;
+}
+
+uid_t geteuid(void)
+{
+ return 0;
+}
+
+gid_t getgid(void)
+{
+ return 0;
+}
+
+gid_t getegid(void)
+{
+ return 0;
+}
+
+int gethostname(char *name, size_t namelen)
+{
+ strncpy(name, "mini-os", namelen);
+ return 0;
+}
+
+size_t getpagesize(void)
+{
+ return PAGE_SIZE;
+}
+
+void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
+{
+ unsigned long n = (length + PAGE_SIZE - 1) / PAGE_SIZE;
+
+ ASSERT(!start);
+ ASSERT(prot == (PROT_READ|PROT_WRITE));
+ ASSERT((fd == -1 && (flags == (MAP_SHARED|MAP_ANON) || flags == (MAP_PRIVATE|MAP_ANON)))
+ || (fd != -1 && flags == MAP_SHARED));
+
+ if (fd == -1)
+ return map_zero(n, 1);
+#ifdef CONFIG_XC
+ else if (files[fd].type == FTYPE_XC) {
+ unsigned long zero = 0;
+ return map_frames_ex(&zero, n, 0, 0, 1, DOMID_SELF, NULL, 0);
+ }
+#endif
+ else if (files[fd].type == FTYPE_MEM) {
+ unsigned long first_mfn = offset >> PAGE_SHIFT;
+ return map_frames_ex(&first_mfn, n, 0, 1, 1, DOMID_IO, NULL, _PAGE_PRESENT|_PAGE_RW);
+ } else ASSERT(0);
+}
+
+int munmap(void *start, size_t length)
+{
+ int total = length / PAGE_SIZE;
+ int ret;
+
+ ret = unmap_frames((unsigned long)start, (unsigned long)total);
+ if (ret) {
+ errno = ret;
+ return -1;
+ }
+ return 0;
+}
+
+void sparse(unsigned long data, size_t size)
+{
+ unsigned long newdata;
+ xen_pfn_t *mfns;
+ int i, n;
+
+ newdata = (data + PAGE_SIZE - 1) & PAGE_MASK;
+ if (newdata - data > size)
+ return;
+ size -= newdata - data;
+ data = newdata;
+ n = size / PAGE_SIZE;
+ size = n * PAGE_SIZE;
+
+ mfns = malloc(n * sizeof(*mfns));
+ for (i = 0; i < n; i++) {
+#ifdef LIBC_DEBUG
+ int j;
+ for (j=0; j<PAGE_SIZE; j++)
+ if (((char*)data + i * PAGE_SIZE)[j]) {
+ printk("%lx is not zero!\n", data + i * PAGE_SIZE + j);
+ exit(1);
+ }
+#endif
+ mfns[i] = virtual_to_mfn(data + i * PAGE_SIZE);
+ }
+
+ printk("sparsing %ldMB at %lx\n", size >> 20, data);
+
+ munmap((void *) data, size);
+ free_physical_pages(mfns, n);
+ do_map_zero(data, n);
+}
+
+int nice(int inc)
+{
+ printk("nice() stub called with inc=%d\n", inc);
+ return 0;
+}
+
+
+/* Not supported by FS yet. */
+unsupported_function_crash(link);
+unsupported_function(int, readlink, -1);
+unsupported_function_crash(umask);
+
+/* We could support that. */
+unsupported_function_log(int, chdir, -1);
+
+/* No dynamic library support. */
+unsupported_function_log(void *, dlopen, NULL);
+unsupported_function_log(void *, dlsym, NULL);
+unsupported_function_log(char *, dlerror, NULL);
+unsupported_function_log(int, dlclose, -1);
+
+/* We don't raise signals anyway. */
+unsupported_function(int, sigemptyset, -1);
+unsupported_function(int, sigfillset, -1);
+unsupported_function(int, sigaddset, -1);
+unsupported_function(int, sigdelset, -1);
+unsupported_function(int, sigismember, -1);
+unsupported_function(int, sigprocmask, -1);
+unsupported_function(int, sigaction, -1);
+unsupported_function(int, __sigsetjmp, 0);
+unsupported_function(int, sigaltstack, -1);
+unsupported_function_crash(kill);
+
+/* Unsupported */
+unsupported_function_crash(pipe);
+unsupported_function_crash(fork);
+unsupported_function_crash(execv);
+unsupported_function_crash(execve);
+unsupported_function_crash(waitpid);
+unsupported_function_crash(wait);
+unsupported_function_crash(lockf);
+unsupported_function_crash(sysconf);
+unsupported_function(int, tcsetattr, -1);
+unsupported_function(int, tcgetattr, 0);
+unsupported_function(int, grantpt, -1);
+unsupported_function(int, unlockpt, -1);
+unsupported_function(char *, ptsname, NULL);
+
+/* net/if.h */
+unsupported_function_log(unsigned int, if_nametoindex, -1);
+unsupported_function_log(char *, if_indextoname, (char *) NULL);
+unsupported_function_log(struct if_nameindex *, if_nameindex, (struct if_nameindex *) NULL);
+unsupported_function_crash(if_freenameindex);
+
+/* Linuxish abi for the Caml runtime, don't support
+ Log, and return an error code if possible. If it is not possible
+ to inform the application of an error, then crash instead!
+*/
+unsupported_function_log(struct dirent *, readdir64, NULL);
+unsupported_function_log(int, getrusage, -1);
+unsupported_function_log(int, getrlimit, -1);
+unsupported_function_log(int, getrlimit64, -1);
+unsupported_function_log(int, __xstat64, -1);
+unsupported_function_log(long, __strtol_internal, LONG_MIN);
+unsupported_function_log(double, __strtod_internal, HUGE_VAL);
+unsupported_function_log(int, utime, -1);
+unsupported_function_log(int, truncate64, -1);
+unsupported_function_log(int, tcflow, -1);
+unsupported_function_log(int, tcflush, -1);
+unsupported_function_log(int, tcdrain, -1);
+unsupported_function_log(int, tcsendbreak, -1);
+unsupported_function_log(int, cfsetospeed, -1);
+unsupported_function_log(int, cfsetispeed, -1);
+unsupported_function_crash(cfgetospeed);
+unsupported_function_crash(cfgetispeed);
+unsupported_function_log(int, symlink, -1);
+unsupported_function_log(const char*, inet_ntop, NULL);
+unsupported_function_crash(__fxstat64);
+unsupported_function_crash(__lxstat64);
+unsupported_function_log(int, socketpair, -1);
+unsupported_function_crash(sigsuspend);
+unsupported_function_log(int, sigpending, -1);
+unsupported_function_log(int, shutdown, -1);
+unsupported_function_log(int, setuid, -1);
+unsupported_function_log(int, setgid, -1);
+unsupported_function_crash(rewinddir);
+unsupported_function_log(int, getpriority, -1);
+unsupported_function_log(int, setpriority, -1);
+unsupported_function_log(int, mkfifo, -1);
+unsupported_function_log(int, getitimer, -1);
+unsupported_function_log(int, setitimer, -1);
+unsupported_function_log(void *, getservbyport, NULL);
+unsupported_function_log(void *, getservbyname, NULL);
+unsupported_function_log(void *, getpwuid, NULL);
+unsupported_function_log(void *, getpwnam, NULL);
+unsupported_function_log(void *, getprotobynumber, NULL);
+unsupported_function_log(void *, getprotobyname, NULL);
+unsupported_function_log(int, getpeername, -1);
+unsupported_function_log(int, getnameinfo, -1);
+unsupported_function_log(char *, getlogin, NULL);
+unsupported_function_crash(__h_errno_location);
+unsupported_function_log(int, gethostbyname_r, -1);
+unsupported_function_log(int, gethostbyaddr_r, -1);
+unsupported_function_log(int, getgroups, -1);
+unsupported_function_log(void *, getgrgid, NULL);
+unsupported_function_log(void *, getgrnam, NULL);
+unsupported_function_log(int, getaddrinfo, -1);
+unsupported_function_log(int, freeaddrinfo, -1);
+unsupported_function_log(int, ftruncate64, -1);
+unsupported_function_log(int, fchown, -1);
+unsupported_function_log(int, fchmod, -1);
+unsupported_function_crash(execvp);
+unsupported_function_log(int, dup, -1)
+unsupported_function_log(int, chroot, -1)
+unsupported_function_log(int, chown, -1);
+unsupported_function_log(int, chmod, -1);
+unsupported_function_crash(alarm);
+unsupported_function_log(int, inet_pton, -1);
+unsupported_function_log(int, access, -1);
+#endif
--- /dev/null
+/*
+ ****************************************************************************
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: xmaloc.c
+ * Author: Grzegorz Milos (gm281@cam.ac.uk)
+ * Samuel Thibault (samuel.thibault@eu.citrix.com)
+ * Changes:
+ *
+ * Date: Aug 2005
+ * Jan 2008
+ *
+ * Environment: Xen Minimal OS
+ * Description: simple memory allocator
+ *
+ ****************************************************************************
+ * Simple allocator for Mini-os. If larger than a page, simply use the
+ * page-order allocator.
+ *
+ * Copy of the allocator for Xen by Rusty Russell:
+ * Copyright (C) 2005 Rusty Russell IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <mini-os/types.h>
+#include <mini-os/lib.h>
+#include <mini-os/list.h>
+#include <mini-os/xmalloc.h>
+
+#ifndef HAVE_LIBC
+/* static spinlock_t freelist_lock = SPIN_LOCK_UNLOCKED; */
+
+struct xmalloc_hdr
+{
+ /* Total including this hdr, unused padding and second hdr. */
+ size_t size;
+ MINIOS_TAILQ_ENTRY(struct xmalloc_hdr) freelist;
+} __cacheline_aligned;
+
+static MINIOS_TAILQ_HEAD(,struct xmalloc_hdr) freelist =
+ MINIOS_TAILQ_HEAD_INITIALIZER(freelist);
+
+/* Unused padding data between the two hdrs. */
+
+struct xmalloc_pad
+{
+ /* Size including both hdrs. */
+ size_t hdr_size;
+};
+
+/* Return size, increased to alignment with align. */
+static inline size_t align_up(size_t size, size_t align)
+{
+ return (size + align - 1) & ~(align - 1);
+}
+
+static void maybe_split(struct xmalloc_hdr *hdr, size_t size, size_t block)
+{
+ struct xmalloc_hdr *extra;
+ size_t leftover;
+ size = align_up(size, __alignof__(struct xmalloc_hdr));
+ size = align_up(size, __alignof__(struct xmalloc_pad));
+ leftover = block - size;
+
+ /* If enough is left to make a block, put it on free list. */
+ if ( leftover >= (2 * (sizeof(struct xmalloc_hdr) + sizeof(struct xmalloc_pad))) )
+ {
+ extra = (struct xmalloc_hdr *)((unsigned long)hdr + size);
+ extra->size = leftover;
+ /* spin_lock_irqsave(&freelist_lock, flags); */
+ MINIOS_TAILQ_INSERT_HEAD(&freelist, extra, freelist);
+ /* spin_unlock_irqrestore(&freelist_lock, flags); */
+ }
+ else
+ {
+ size = block;
+ }
+
+ hdr->size = size;
+}
+
+static struct xmalloc_hdr *xmalloc_new_page(size_t size)
+{
+ struct xmalloc_hdr *hdr;
+ /* unsigned long flags; */
+
+ hdr = (struct xmalloc_hdr *)alloc_page();
+ if ( hdr == NULL )
+ return NULL;
+
+ maybe_split(hdr, size, PAGE_SIZE);
+
+ return hdr;
+}
+
+/* Big object? Just use the page allocator. */
+static void *xmalloc_whole_pages(size_t size, size_t align)
+{
+ struct xmalloc_hdr *hdr;
+ struct xmalloc_pad *pad;
+ unsigned int pageorder;
+ void *ret;
+ /* Room for headers */
+ size_t hdr_size = sizeof(struct xmalloc_hdr) + sizeof(struct xmalloc_pad);
+ /* Align for actual beginning of data */
+ hdr_size = align_up(hdr_size, align);
+
+ pageorder = get_order(hdr_size + size);
+
+ hdr = (struct xmalloc_hdr *)alloc_pages(pageorder);
+ if ( hdr == NULL )
+ return NULL;
+
+ hdr->size = (1UL << (pageorder + PAGE_SHIFT));
+
+ ret = (char*)hdr + hdr_size;
+ pad = (struct xmalloc_pad *) ret - 1;
+ pad->hdr_size = hdr_size;
+ return ret;
+}
+
+void *_xmalloc(size_t size, size_t align)
+{
+ struct xmalloc_hdr *i, *tmp, *hdr = NULL;
+ uintptr_t data_begin;
+ size_t hdr_size;
+ /* unsigned long flags; */
+
+ hdr_size = sizeof(struct xmalloc_hdr) + sizeof(struct xmalloc_pad);
+ /* Align on headers requirements. */
+ align = align_up(align, __alignof__(struct xmalloc_hdr));
+ align = align_up(align, __alignof__(struct xmalloc_pad));
+
+ /* For big allocs, give them whole pages. */
+ if ( size + align_up(hdr_size, align) >= PAGE_SIZE )
+ return xmalloc_whole_pages(size, align);
+
+ /* Search free list. */
+ /* spin_lock_irqsave(&freelist_lock, flags); */
+ MINIOS_TAILQ_FOREACH_SAFE(i, &freelist, freelist, tmp)
+ {
+ data_begin = align_up((uintptr_t)i + hdr_size, align);
+
+ if ( data_begin + size > (uintptr_t)i + i->size )
+ continue;
+
+ MINIOS_TAILQ_REMOVE(&freelist, i, freelist);
+ /* spin_unlock_irqrestore(&freelist_lock, flags); */
+
+ uintptr_t size_before = (data_begin - hdr_size) - (uintptr_t)i;
+
+ if (size_before >= 2 * hdr_size) {
+ /* Worth splitting the beginning */
+ struct xmalloc_hdr *new_i = (void*)(data_begin - hdr_size);
+ new_i->size = i->size - size_before;
+ i->size = size_before;
+ /* spin_lock_irqsave(&freelist_lock, flags); */
+ MINIOS_TAILQ_INSERT_HEAD(&freelist, i, freelist);
+ /* spin_unlock_irqrestore(&freelist_lock, flags); */
+ i = new_i;
+ }
+ maybe_split(i, (data_begin + size) - (uintptr_t)i, i->size);
+ hdr = i;
+ break;
+ }
+
+ if (!hdr) {
+ /* spin_unlock_irqrestore(&freelist_lock, flags); */
+
+ /* Alloc a new page and return from that. */
+ hdr = xmalloc_new_page(align_up(hdr_size, align) + size);
+ if ( hdr == NULL )
+ return NULL;
+ data_begin = (uintptr_t)hdr + align_up(hdr_size, align);
+ }
+
+ struct xmalloc_pad *pad = (struct xmalloc_pad *) data_begin - 1;
+ pad->hdr_size = data_begin - (uintptr_t)hdr;
+ BUG_ON(data_begin % align);
+ return (void*)data_begin;
+}
+
+void xfree(const void *p)
+{
+ /* unsigned long flags; */
+ struct xmalloc_hdr *i, *tmp, *hdr;
+ struct xmalloc_pad *pad;
+
+ if ( p == NULL )
+ return;
+
+ pad = (struct xmalloc_pad *)p - 1;
+ hdr = (struct xmalloc_hdr *)((char *)p - pad->hdr_size);
+
+ /* Big allocs free directly. */
+ if ( hdr->size >= PAGE_SIZE )
+ {
+ free_pages(hdr, get_order(hdr->size));
+ return;
+ }
+
+ /* We know hdr will be on same page. */
+ if(((long)p & PAGE_MASK) != ((long)hdr & PAGE_MASK))
+ {
+ printk("Header should be on the same page\n");
+ *(int*)0=0;
+ }
+
+ /* Merge with other free block, or put in list. */
+ /* spin_lock_irqsave(&freelist_lock, flags); */
+ MINIOS_TAILQ_FOREACH_SAFE(i, &freelist, freelist, tmp)
+ {
+ unsigned long _i = (unsigned long)i;
+ unsigned long _hdr = (unsigned long)hdr;
+
+ /* Do not merge across page boundaries. */
+ if ( ((_i ^ _hdr) & PAGE_MASK) != 0 )
+ continue;
+
+ /* We follow this block? Swallow it. */
+ if ( (_i + i->size) == _hdr )
+ {
+ MINIOS_TAILQ_REMOVE(&freelist, i, freelist);
+ i->size += hdr->size;
+ hdr = i;
+ }
+
+ /* We precede this block? Swallow it. */
+ if ( (_hdr + hdr->size) == _i )
+ {
+ MINIOS_TAILQ_REMOVE(&freelist, i, freelist);
+ hdr->size += i->size;
+ }
+ }
+
+ /* Did we merge an entire page? */
+ if ( hdr->size == PAGE_SIZE )
+ {
+ if((((unsigned long)hdr) & (PAGE_SIZE-1)) != 0)
+ {
+ printk("Bug\n");
+ *(int*)0=0;
+ }
+ free_page(hdr);
+ }
+ else
+ {
+ MINIOS_TAILQ_INSERT_HEAD(&freelist, hdr, freelist);
+ }
+
+ /* spin_unlock_irqrestore(&freelist_lock, flags); */
+}
+
+void *malloc(size_t size)
+{
+ return _xmalloc(size, DEFAULT_ALIGN);
+}
+
+void *realloc(void *ptr, size_t size)
+{
+ void *new;
+ struct xmalloc_hdr *hdr;
+ struct xmalloc_pad *pad;
+ size_t old_data_size;
+
+ if (ptr == NULL)
+ return _xmalloc(size, DEFAULT_ALIGN);
+
+ pad = (struct xmalloc_pad *)ptr - 1;
+ hdr = (struct xmalloc_hdr *)((char*)ptr - pad->hdr_size);
+
+ old_data_size = hdr->size - pad->hdr_size;
+ if ( old_data_size >= size )
+ {
+ maybe_split(hdr, pad->hdr_size + size, hdr->size);
+ return ptr;
+ }
+
+ new = _xmalloc(size, DEFAULT_ALIGN);
+ if (new == NULL)
+ return NULL;
+
+ memcpy(new, ptr, old_data_size);
+ xfree(ptr);
+
+ return new;
+}
+
+void free(void *ptr)
+{
+ xfree(ptr);
+}
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/*
+ * libxs-compatible layer
+ *
+ * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, 2007-2008
+ *
+ * Mere wrapper around xenbus_*
+ */
+
+#ifdef HAVE_LIBC
+#include <os.h>
+#include <lib.h>
+#include <xenstore.h>
+#include <xenbus.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static inline int _xs_fileno(struct xs_handle *h) {
+ return (intptr_t) h;
+}
+
+struct xs_handle *xs_daemon_open()
+{
+ int fd = alloc_fd(FTYPE_XENBUS);
+ files[fd].xenbus.events = NULL;
+ printk("xs_daemon_open -> %d, %p\n", fd, &files[fd].xenbus.events);
+ return (void*)(intptr_t) fd;
+}
+
+void xs_daemon_close(struct xs_handle *h)
+{
+ int fd = _xs_fileno(h);
+ struct xenbus_event *event, *next;
+ for (event = files[fd].xenbus.events; event; event = next)
+ {
+ next = event->next;
+ free(event);
+ }
+ files[fd].type = FTYPE_NONE;
+}
+
+int xs_fileno(struct xs_handle *h)
+{
+ return _xs_fileno(h);
+}
+
+void *xs_read(struct xs_handle *h, xs_transaction_t t,
+ const char *path, unsigned int *len)
+{
+ char *value;
+ char *msg;
+
+ msg = xenbus_read(t, path, &value);
+ if (msg) {
+ printk("xs_read(%s): %s\n", path, msg);
+ free(msg);
+ return NULL;
+ }
+
+ if (len)
+ *len = strlen(value);
+ return value;
+}
+
+bool xs_write(struct xs_handle *h, xs_transaction_t t,
+ const char *path, const void *data, unsigned int len)
+{
+ char value[len + 1];
+ char *msg;
+
+ memcpy(value, data, len);
+ value[len] = 0;
+
+ msg = xenbus_write(t, path, value);
+ if (msg) {
+ printk("xs_write(%s): %s\n", path, msg);
+ free(msg);
+ return false;
+ }
+ return true;
+}
+
+static bool xs_bool(char *reply)
+{
+ if (!reply)
+ return true;
+ free(reply);
+ return false;
+}
+
+bool xs_rm(struct xs_handle *h, xs_transaction_t t, const char *path)
+{
+ return xs_bool(xenbus_rm(t, path));
+}
+
+static void *xs_talkv(struct xs_handle *h, xs_transaction_t t,
+ enum xsd_sockmsg_type type,
+ struct write_req *iovec,
+ unsigned int num_vecs,
+ unsigned int *len)
+{
+ struct xsd_sockmsg *msg;
+ void *ret;
+
+ msg = xenbus_msg_reply(type, t, iovec, num_vecs);
+ ret = malloc(msg->len);
+ memcpy(ret, (char*) msg + sizeof(*msg), msg->len);
+ if (len)
+ *len = msg->len - 1;
+ free(msg);
+ return ret;
+}
+
+static void *xs_single(struct xs_handle *h, xs_transaction_t t,
+ enum xsd_sockmsg_type type,
+ const char *string,
+ unsigned int *len)
+{
+ struct write_req iovec;
+
+ iovec.data = (void *)string;
+ iovec.len = strlen(string) + 1;
+
+ return xs_talkv(h, t, type, &iovec, 1, len);
+}
+
+char *xs_get_domain_path(struct xs_handle *h, unsigned int domid)
+{
+ char domid_str[MAX_STRLEN(domid)];
+
+ sprintf(domid_str, "%u", domid);
+
+ return xs_single(h, XBT_NULL, XS_GET_DOMAIN_PATH, domid_str, NULL);
+}
+
+char **xs_directory(struct xs_handle *h, xs_transaction_t t,
+ const char *path, unsigned int *num)
+{
+ char *msg;
+ char **entries, **res;
+ char *entry;
+ int i, n;
+ int size;
+
+ msg = xenbus_ls(t, path, &res);
+ if (msg) {
+ printk("xs_directory(%s): %s\n", path, msg);
+ free(msg);
+ return NULL;
+ }
+
+ size = 0;
+ for (n = 0; res[n]; n++)
+ size += strlen(res[n]) + 1;
+
+ entries = malloc(n * sizeof(char *) + size);
+ entry = (char *) (&entries[n]);
+
+ for (i = 0; i < n; i++) {
+ int l = strlen(res[i]) + 1;
+ memcpy(entry, res[i], l);
+ free(res[i]);
+ entries[i] = entry;
+ entry += l;
+ }
+
+ *num = n;
+ free(res);
+ return entries;
+}
+
+bool xs_watch(struct xs_handle *h, const char *path, const char *token)
+{
+ int fd = _xs_fileno(h);
+ printk("xs_watch(%s, %s)\n", path, token);
+ return xs_bool(xenbus_watch_path_token(XBT_NULL, path, token, &files[fd].xenbus.events));
+}
+
+char **xs_read_watch(struct xs_handle *h, unsigned int *num)
+{
+ int fd = _xs_fileno(h);
+ struct xenbus_event *event;
+ event = files[fd].xenbus.events;
+ files[fd].xenbus.events = event->next;
+ printk("xs_read_watch() -> %s %s\n", event->path, event->token);
+ *num = 2;
+ return (char **) &event->path;
+}
+
+bool xs_unwatch(struct xs_handle *h, const char *path, const char *token)
+{
+ printk("xs_unwatch(%s, %s)\n", path, token);
+ return xs_bool(xenbus_unwatch_path_token(XBT_NULL, path, token));
+}
+#endif
--- /dev/null
+/*
+ * locks for newlib
+ *
+ * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, July 20008
+ */
+
+#ifdef HAVE_LIBC
+
+#include <sys/lock.h>
+#include <sched.h>
+#include <wait.h>
+#include <mini-os/lib.h>
+
+int ___lock_init(_LOCK_T *lock)
+{
+ lock->busy = 0;
+ init_waitqueue_head(&lock->wait);
+ return 0;
+}
+
+int ___lock_acquire(_LOCK_T *lock)
+{
+ unsigned long flags;
+ while(1) {
+ wait_event(lock->wait, !lock->busy);
+ local_irq_save(flags);
+ if (!lock->busy)
+ break;
+ local_irq_restore(flags);
+ }
+ lock->busy = 1;
+ local_irq_restore(flags);
+ return 0;
+}
+
+int ___lock_try_acquire(_LOCK_T *lock)
+{
+ unsigned long flags;
+ int ret = -1;
+ local_irq_save(flags);
+ if (!lock->busy) {
+ lock->busy = 1;
+ ret = 0;
+ }
+ local_irq_restore(flags);
+ return ret;
+}
+
+int ___lock_release(_LOCK_T *lock)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+ lock->busy = 0;
+ wake_up(&lock->wait);
+ local_irq_restore(flags);
+ return 0;
+}
+
+
+int ___lock_init_recursive(_LOCK_RECURSIVE_T *lock)
+{
+ lock->owner = NULL;
+ init_waitqueue_head(&lock->wait);
+ return 0;
+}
+
+int ___lock_acquire_recursive(_LOCK_RECURSIVE_T *lock)
+{
+ unsigned long flags;
+ if (lock->owner != get_current()) {
+ while (1) {
+ wait_event(lock->wait, lock->owner == NULL);
+ local_irq_save(flags);
+ if (lock->owner == NULL)
+ break;
+ local_irq_restore(flags);
+ }
+ lock->owner = get_current();
+ local_irq_restore(flags);
+ }
+ lock->count++;
+ return 0;
+}
+
+int ___lock_try_acquire_recursive(_LOCK_RECURSIVE_T *lock)
+{
+ unsigned long flags;
+ int ret = -1;
+ local_irq_save(flags);
+ if (!lock->owner) {
+ ret = 0;
+ lock->owner = get_current();
+ lock->count++;
+ }
+ local_irq_restore(flags);
+ return ret;
+}
+
+int ___lock_release_recursive(_LOCK_RECURSIVE_T *lock)
+{
+ unsigned long flags;
+ BUG_ON(lock->owner != get_current());
+ if (--lock->count)
+ return 0;
+ local_irq_save(flags);
+ lock->owner = NULL;
+ wake_up(&lock->wait);
+ local_irq_restore(flags);
+ return 0;
+}
+
+#endif
--- /dev/null
+/*
+ * lwip-arch.c
+ *
+ * Arch-specific semaphores and mailboxes for lwIP running on mini-os
+ *
+ * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
+ */
+
+#include <os.h>
+#include <time.h>
+#include <console.h>
+#include <xmalloc.h>
+#include <lwip/sys.h>
+#include <stdarg.h>
+
+/* Is called to initialize the sys_arch layer */
+void sys_init(void)
+{
+}
+
+/* Creates and returns a new semaphore. The "count" argument specifies
+ * the initial state of the semaphore. */
+sys_sem_t sys_sem_new(uint8_t count)
+{
+ struct semaphore *sem = xmalloc(struct semaphore);
+ sem->count = count;
+ init_waitqueue_head(&sem->wait);
+ return sem;
+}
+
+/* Deallocates a semaphore. */
+void sys_sem_free(sys_sem_t sem)
+{
+ xfree(sem);
+}
+
+/* Signals a semaphore. */
+void sys_sem_signal(sys_sem_t sem)
+{
+ up(sem);
+}
+
+/* Blocks the thread while waiting for the semaphore to be
+ * signaled. If the "timeout" argument is non-zero, the thread should
+ * only be blocked for the specified time (measured in
+ * milliseconds).
+ *
+ * If the timeout argument is non-zero, the return value is the number of
+ * milliseconds spent waiting for the semaphore to be signaled. If the
+ * semaphore wasn't signaled within the specified time, the return value is
+ * SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
+ * (i.e., it was already signaled), the function may return zero. */
+uint32_t sys_arch_sem_wait(sys_sem_t sem, uint32_t timeout)
+{
+ /* Slightly more complicated than the normal minios semaphore:
+ * need to wake on timeout *or* signal */
+ sys_prot_t prot;
+ int64_t then = NOW();
+ int64_t deadline;
+
+ if (timeout == 0)
+ deadline = 0;
+ else
+ deadline = then + MILLISECS(timeout);
+
+ while(1) {
+ wait_event_deadline(sem->wait, (sem->count > 0), deadline);
+
+ prot = sys_arch_protect();
+ /* Atomically check that we can proceed */
+ if (sem->count > 0 || (deadline && NOW() >= deadline))
+ break;
+ sys_arch_unprotect(prot);
+ }
+
+ if (sem->count > 0) {
+ sem->count--;
+ sys_arch_unprotect(prot);
+ return NSEC_TO_MSEC(NOW() - then);
+ }
+
+ sys_arch_unprotect(prot);
+ return SYS_ARCH_TIMEOUT;
+}
+
+/* Creates an empty mailbox. */
+sys_mbox_t sys_mbox_new(int size)
+{
+ struct mbox *mbox = xmalloc(struct mbox);
+ if (!size)
+ size = 32;
+ else if (size == 1)
+ size = 2;
+ mbox->count = size;
+ mbox->messages = xmalloc_array(void*, size);
+ init_SEMAPHORE(&mbox->read_sem, 0);
+ mbox->reader = 0;
+ init_SEMAPHORE(&mbox->write_sem, size);
+ mbox->writer = 0;
+ return mbox;
+}
+
+/* Deallocates a mailbox. If there are messages still present in the
+ * mailbox when the mailbox is deallocated, it is an indication of a
+ * programming error in lwIP and the developer should be notified. */
+void sys_mbox_free(sys_mbox_t mbox)
+{
+ ASSERT(mbox->reader == mbox->writer);
+ xfree(mbox->messages);
+ xfree(mbox);
+}
+
+/* Posts the "msg" to the mailbox, internal version that actually does the
+ * post. */
+static void do_mbox_post(sys_mbox_t mbox, void *msg)
+{
+ /* The caller got a semaphore token, so we are now allowed to increment
+ * writer, but we still need to prevent concurrency between writers
+ * (interrupt handler vs main) */
+ sys_prot_t prot = sys_arch_protect();
+ mbox->messages[mbox->writer] = msg;
+ mbox->writer = (mbox->writer + 1) % mbox->count;
+ ASSERT(mbox->reader != mbox->writer);
+ sys_arch_unprotect(prot);
+ up(&mbox->read_sem);
+}
+
+/* Posts the "msg" to the mailbox. */
+void sys_mbox_post(sys_mbox_t mbox, void *msg)
+{
+ if (mbox == SYS_MBOX_NULL)
+ return;
+ down(&mbox->write_sem);
+ do_mbox_post(mbox, msg);
+}
+
+/* Try to post the "msg" to the mailbox. */
+err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg)
+{
+ if (mbox == SYS_MBOX_NULL)
+ return ERR_BUF;
+ if (!trydown(&mbox->write_sem))
+ return ERR_MEM;
+ do_mbox_post(mbox, msg);
+ return ERR_OK;
+}
+
+/*
+ * Fetch a message from a mailbox. Internal version that actually does the
+ * fetch.
+ */
+static void do_mbox_fetch(sys_mbox_t mbox, void **msg)
+{
+ sys_prot_t prot;
+ /* The caller got a semaphore token, so we are now allowed to increment
+ * reader, but we may still need to prevent concurrency between readers.
+ * FIXME: can there be concurrent readers? */
+ prot = sys_arch_protect();
+ ASSERT(mbox->reader != mbox->writer);
+ if (msg != NULL)
+ *msg = mbox->messages[mbox->reader];
+ mbox->reader = (mbox->reader + 1) % mbox->count;
+ sys_arch_unprotect(prot);
+ up(&mbox->write_sem);
+}
+
+/* Blocks the thread until a message arrives in the mailbox, but does
+ * not block the thread longer than "timeout" milliseconds (similar to
+ * the sys_arch_sem_wait() function). The "msg" argument is a result
+ * parameter that is set by the function (i.e., by doing "*msg =
+ * ptr"). The "msg" parameter maybe NULL to indicate that the message
+ * should be dropped.
+ *
+ * The return values are the same as for the sys_arch_sem_wait() function:
+ * Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
+ * timeout. */
+uint32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, uint32_t timeout)
+{
+ uint32_t rv;
+ if (mbox == SYS_MBOX_NULL)
+ return SYS_ARCH_TIMEOUT;
+
+ rv = sys_arch_sem_wait(&mbox->read_sem, timeout);
+ if ( rv == SYS_ARCH_TIMEOUT )
+ return rv;
+
+ do_mbox_fetch(mbox, msg);
+ return 0;
+}
+
+/* This is similar to sys_arch_mbox_fetch, however if a message is not
+ * present in the mailbox, it immediately returns with the code
+ * SYS_MBOX_EMPTY. On success 0 is returned.
+ *
+ * To allow for efficient implementations, this can be defined as a
+ * function-like macro in sys_arch.h instead of a normal function. For
+ * example, a naive implementation could be:
+ * #define sys_arch_mbox_tryfetch(mbox,msg) \
+ * sys_arch_mbox_fetch(mbox,msg,1)
+ * although this would introduce unnecessary delays. */
+
+uint32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg) {
+ if (mbox == SYS_MBOX_NULL)
+ return SYS_ARCH_TIMEOUT;
+
+ if (!trydown(&mbox->read_sem))
+ return SYS_MBOX_EMPTY;
+
+ do_mbox_fetch(mbox, msg);
+ return 0;
+}
+
+
+/* Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
+ * each thread has a list of timeouts which is repressented as a linked
+ * list of sys_timeout structures. The sys_timeouts structure holds a
+ * pointer to a linked list of timeouts. This function is called by
+ * the lwIP timeout scheduler and must not return a NULL value.
+ *
+ * In a single threadd sys_arch implementation, this function will
+ * simply return a pointer to a global sys_timeouts variable stored in
+ * the sys_arch module. */
+struct sys_timeouts *sys_arch_timeouts(void)
+{
+ static struct sys_timeouts timeout;
+ return &timeout;
+}
+
+
+/* Starts a new thread with priority "prio" that will begin its execution in the
+ * function "thread()". The "arg" argument will be passed as an argument to the
+ * thread() function. The id of the new thread is returned. Both the id and
+ * the priority are system dependent. */
+static struct thread *lwip_thread;
+sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio)
+{
+ struct thread *t;
+ if (stacksize > STACK_SIZE) {
+ printk("Can't start lwIP thread: stack size %d is too large for our %d\n", stacksize, STACK_SIZE);
+ do_exit();
+ }
+ lwip_thread = t = create_thread(name, thread, arg);
+ return t;
+}
+
+/* This optional function does a "fast" critical region protection and returns
+ * the previous protection level. This function is only called during very short
+ * critical regions. An embedded system which supports ISR-based drivers might
+ * want to implement this function by disabling interrupts. Task-based systems
+ * might want to implement this by using a mutex or disabling tasking. This
+ * function should support recursive calls from the same task or interrupt. In
+ * other words, sys_arch_protect() could be called while already protected. In
+ * that case the return value indicates that it is already protected.
+ *
+ * sys_arch_protect() is only required if your port is supporting an operating
+ * system. */
+sys_prot_t sys_arch_protect(void)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+ return flags;
+}
+
+/* This optional function does a "fast" set of critical region protection to the
+ * value specified by pval. See the documentation for sys_arch_protect() for
+ * more information. This function is only required if your port is supporting
+ * an operating system. */
+void sys_arch_unprotect(sys_prot_t pval)
+{
+ local_irq_restore(pval);
+}
+
+/* non-fatal, print a message. */
+void lwip_printk(char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ printk("lwIP: ");
+ print(0, fmt, args);
+ va_end(args);
+}
+
+/* fatal, print message and abandon execution. */
+void lwip_die(char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ printk("lwIP assertion failed: ");
+ print(0, fmt, args);
+ va_end(args);
+ printk("\n");
+ BUG();
+}
--- /dev/null
+/*
+ * lwip-net.c
+ *
+ * interface between lwIP's ethernet and Mini-os's netfront.
+ * For now, support only one network interface, as mini-os does.
+ *
+ * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
+ * based on lwIP's ethernetif.c skeleton file, copyrights as below.
+ */
+
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#include <os.h>
+
+#include "lwip/opt.h"
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+
+#include <lwip/stats.h>
+#include <lwip/sys.h>
+#include <lwip/mem.h>
+#include <lwip/memp.h>
+#include <lwip/pbuf.h>
+#include <netif/etharp.h>
+#include <lwip/tcpip.h>
+#include <lwip/tcp.h>
+#include <lwip/netif.h>
+#include <lwip/dhcp.h>
+
+#include "netif/etharp.h"
+
+#include <netfront.h>
+
+/* Define those to better describe your network interface. */
+#define IFNAME0 'e'
+#define IFNAME1 'n'
+
+#define IF_IPADDR 0x00000000
+#define IF_NETMASK 0x00000000
+
+/* Only have one network interface at a time. */
+static struct netif *the_interface = NULL;
+
+static unsigned char rawmac[6];
+static struct netfront_dev *dev;
+
+/* Forward declarations. */
+static err_t netfront_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr);
+
+/*
+ * low_level_output():
+ *
+ * Should do the actual transmission of the packet. The packet is
+ * contained in the pbuf that is passed to the function. This pbuf
+ * might be chained.
+ *
+ */
+
+static err_t
+low_level_output(struct netif *netif, struct pbuf *p)
+{
+ if (!dev)
+ return ERR_OK;
+
+#ifdef ETH_PAD_SIZE
+ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
+#endif
+
+ /* Send the data from the pbuf to the interface, one pbuf at a
+ time. The size of the data in each pbuf is kept in the ->len
+ variable. */
+ if (!p->next) {
+ /* Only one fragment, can send it directly */
+ netfront_xmit(dev, p->payload, p->len);
+ } else {
+ unsigned char data[p->tot_len], *cur;
+ struct pbuf *q;
+
+ for(q = p, cur = data; q != NULL; cur += q->len, q = q->next)
+ memcpy(cur, q->payload, q->len);
+ netfront_xmit(dev, data, p->tot_len);
+ }
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+
+ LINK_STATS_INC(link.xmit);
+
+ return ERR_OK;
+}
+
+
+
+/*
+ * netfront_output():
+ *
+ * This function is called by the TCP/IP stack when an IP packet
+ * should be sent. It calls the function called low_level_output() to
+ * do the actual transmission of the packet.
+ *
+ */
+
+static err_t
+netfront_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr)
+{
+
+ /* resolve hardware address, then send (or queue) packet */
+ return etharp_output(netif, p, ipaddr);
+
+}
+
+/*
+ * netfront_input():
+ *
+ * This function should be called when a packet is ready to be read
+ * from the interface.
+ *
+ */
+
+static void
+netfront_input(struct netif *netif, unsigned char* data, int len)
+{
+ struct eth_hdr *ethhdr;
+ struct pbuf *p, *q;
+
+#if ETH_PAD_SIZE
+ len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
+#endif
+
+ /* move received packet into a new pbuf */
+ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+ if (p == NULL) {
+ LINK_STATS_INC(link.memerr);
+ LINK_STATS_INC(link.drop);
+ return;
+ }
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
+#endif
+
+ /* We iterate over the pbuf chain until we have read the entire
+ * packet into the pbuf. */
+ for(q = p; q != NULL && len > 0; q = q->next) {
+ /* Read enough bytes to fill this pbuf in the chain. The
+ * available data in the pbuf is given by the q->len
+ * variable. */
+ memcpy(q->payload, data, len < q->len ? len : q->len);
+ data += q->len;
+ len -= q->len;
+ }
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+
+ LINK_STATS_INC(link.recv);
+
+ /* points to packet payload, which starts with an Ethernet header */
+ ethhdr = p->payload;
+
+ switch (htons(ethhdr->type)) {
+ /* IP packet? */
+ case ETHTYPE_IP:
+#if 0
+/* CSi disabled ARP table update on ingress IP packets.
+ This seems to work but needs thorough testing. */
+ /* update ARP table */
+ etharp_ip_input(netif, p);
+#endif
+ /* skip Ethernet header */
+ pbuf_header(p, -(int16_t)sizeof(struct eth_hdr));
+ /* pass to network layer */
+ if (tcpip_input(p, netif) == ERR_MEM)
+ /* Could not store it, drop */
+ pbuf_free(p);
+ break;
+
+ case ETHTYPE_ARP:
+ /* pass p to ARP module */
+ etharp_arp_input(netif, (struct eth_addr *) netif->hwaddr, p);
+ break;
+
+ default:
+ pbuf_free(p);
+ p = NULL;
+ break;
+ }
+}
+
+
+/*
+ * netif_rx(): overrides the default netif_rx behaviour in the netfront driver.
+ *
+ * Pull received packets into a pbuf queue for the low_level_input()
+ * function to pass up to lwIP.
+ */
+
+void netif_rx(unsigned char* data, int len)
+{
+ if (the_interface != NULL) {
+ netfront_input(the_interface, data, len);
+ wake_up(&netfront_queue);
+ }
+ /* By returning, we ack the packet and relinquish the RX ring slot */
+}
+
+/*
+ * Set the IP, mask and gateway of the IF
+ */
+void networking_set_addr(struct ip_addr *ipaddr, struct ip_addr *netmask, struct ip_addr *gw)
+{
+ netif_set_ipaddr(the_interface, ipaddr);
+ netif_set_netmask(the_interface, netmask);
+ netif_set_gw(the_interface, gw);
+}
+
+
+static void
+arp_timer(void *arg)
+{
+ etharp_tmr();
+ sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
+}
+
+/*
+ * netif_netfront_init():
+ *
+ * Should be called at the beginning of the program to set up the
+ * network interface. It calls the function low_level_init() to do the
+ * actual setup of the hardware.
+ *
+ */
+
+err_t
+netif_netfront_init(struct netif *netif)
+{
+ unsigned char *mac = netif->state;
+
+#if LWIP_SNMP
+ /* ifType ethernetCsmacd(6) @see RFC1213 */
+ netif->link_type = 6;
+ /* your link speed here */
+ netif->link_speed = ;
+ netif->ts = 0;
+ netif->ifinoctets = 0;
+ netif->ifinucastpkts = 0;
+ netif->ifinnucastpkts = 0;
+ netif->ifindiscards = 0;
+ netif->ifoutoctets = 0;
+ netif->ifoutucastpkts = 0;
+ netif->ifoutnucastpkts = 0;
+ netif->ifoutdiscards = 0;
+#endif
+
+ netif->name[0] = IFNAME0;
+ netif->name[1] = IFNAME1;
+ netif->output = netfront_output;
+ netif->linkoutput = low_level_output;
+
+ the_interface = netif;
+
+ /* set MAC hardware address */
+ netif->hwaddr_len = 6;
+ netif->hwaddr[0] = mac[0];
+ netif->hwaddr[1] = mac[1];
+ netif->hwaddr[2] = mac[2];
+ netif->hwaddr[3] = mac[3];
+ netif->hwaddr[4] = mac[4];
+ netif->hwaddr[5] = mac[5];
+
+ /* No interesting per-interface state */
+ netif->state = NULL;
+
+ /* maximum transfer unit */
+ netif->mtu = 1500;
+
+ /* broadcast capability */
+ netif->flags = NETIF_FLAG_BROADCAST;
+
+ etharp_init();
+
+ sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
+
+ return ERR_OK;
+}
+
+/*
+ * Thread run by netfront: bring up the IP address and fire lwIP timers.
+ */
+static __DECLARE_SEMAPHORE_GENERIC(tcpip_is_up, 0);
+static void tcpip_bringup_finished(void *p)
+{
+ tprintk("TCP/IP bringup ends.\n");
+ up(&tcpip_is_up);
+}
+
+/*
+ * Utility function to bring the whole lot up. Call this from app_main()
+ * or similar -- it starts netfront and have lwIP start its thread,
+ * which calls back to tcpip_bringup_finished(), which
+ * lets us know it's OK to continue.
+ */
+void start_networking(void)
+{
+ struct netif *netif;
+ struct ip_addr ipaddr = { htonl(IF_IPADDR) };
+ struct ip_addr netmask = { htonl(IF_NETMASK) };
+ struct ip_addr gw = { 0 };
+ char *ip = NULL;
+
+ tprintk("Waiting for network.\n");
+
+ dev = init_netfront(NULL, NULL, rawmac, &ip);
+
+ if (ip) {
+ ipaddr.addr = inet_addr(ip);
+ if (IN_CLASSA(ntohl(ipaddr.addr)))
+ netmask.addr = htonl(IN_CLASSA_NET);
+ else if (IN_CLASSB(ntohl(ipaddr.addr)))
+ netmask.addr = htonl(IN_CLASSB_NET);
+ else if (IN_CLASSC(ntohl(ipaddr.addr)))
+ netmask.addr = htonl(IN_CLASSC_NET);
+ else
+ tprintk("Strange IP %s, leaving netmask to 0.\n", ip);
+ }
+ tprintk("IP %x netmask %x gateway %x.\n",
+ ntohl(ipaddr.addr), ntohl(netmask.addr), ntohl(gw.addr));
+
+ tprintk("TCP/IP bringup begins.\n");
+
+ netif = xmalloc(struct netif);
+ tcpip_init(tcpip_bringup_finished, netif);
+
+ netif_add(netif, &ipaddr, &netmask, &gw, rawmac,
+ netif_netfront_init, ip_input);
+ netif_set_default(netif);
+ netif_set_up(netif);
+
+ down(&tcpip_is_up);
+
+ tprintk("Network is ready.\n");
+}
+
+/* Shut down the network */
+void stop_networking(void)
+{
+ if (dev)
+ shutdown_netfront(dev);
+}
--- /dev/null
+/*
+ * POSIX-compatible main layer
+ *
+ * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, October 2007
+ */
+
+#ifdef HAVE_LIBC
+#include <os.h>
+#include <sched.h>
+#include <console.h>
+#include <netfront.h>
+#include <pcifront.h>
+#include <time.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <xenbus.h>
+#include <events.h>
+#include <mini-os/lib.h>
+
+extern int main(int argc, char *argv[], char *envp[]);
+extern void __libc_init_array(void);
+extern void __libc_fini_array(void);
+extern unsigned long __CTOR_LIST__[];
+extern unsigned long __DTOR_LIST__[];
+
+#if 0
+#include <stdio.h>
+int main(int argc, char *argv[], char *envp[])
+{
+ printf("Hello, World!\n");
+ return 1;
+}
+#endif
+
+void _init(void)
+{
+}
+
+void _fini(void)
+{
+}
+
+extern char __app_bss_start, __app_bss_end;
+static void call_main(void *p)
+{
+ char *c, quote;
+#ifdef CONFIG_QEMU_XS_ARGS
+ char *domargs, *msg;
+#endif
+ int argc;
+ char **argv;
+ char *envp[] = { NULL };
+#ifdef CONFIG_QEMU_XS_ARGS
+ char *vm;
+ char path[128];
+ int domid;
+#endif
+ int i;
+
+ /* Let other parts initialize (including console output) before maybe
+ * crashing. */
+ //sleep(1);
+
+#ifdef CONFIG_SPARSE_BSS
+ sparse((unsigned long) &__app_bss_start, &__app_bss_end - &__app_bss_start);
+#endif
+#if defined(HAVE_LWIP) && defined(CONFIG_START_NETWORK) && defined(CONFIG_NETFRONT)
+ start_networking();
+#endif
+#ifdef CONFIG_PCIFRONT
+ create_thread("pcifront", pcifront_watches, NULL);
+#endif
+
+#ifdef CONFIG_QEMU_XS_ARGS
+ /* Fetch argc, argv from XenStore */
+ domid = xenbus_read_integer("target");
+ if (domid == -1) {
+ printk("Couldn't read target\n");
+ do_exit();
+ }
+
+ snprintf(path, sizeof(path), "/local/domain/%d/vm", domid);
+ msg = xenbus_read(XBT_NIL, path, &vm);
+ if (msg) {
+ printk("Couldn't read vm path\n");
+ do_exit();
+ }
+ printk("dom vm is at %s\n", vm);
+
+ snprintf(path, sizeof(path), "%s/image/dmargs", vm);
+ free(vm);
+ msg = xenbus_read(XBT_NIL, path, &domargs);
+
+ if (msg) {
+ printk("Couldn't get stubdom args: %s\n", msg);
+ domargs = strdup("");
+ }
+#endif
+
+ argc = 1;
+
+#define PARSE_ARGS(ARGS,START,QUOTE,END) \
+ c = ARGS; \
+ quote = 0; \
+ while (*c) { \
+ if (*c != ' ') { \
+ START; \
+ while (*c) { \
+ if (quote) { \
+ if (*c == quote) { \
+ quote = 0; \
+ QUOTE; \
+ continue; \
+ } \
+ } else if (*c == ' ') \
+ break; \
+ if (*c == '"' || *c == '\'') { \
+ quote = *c; \
+ QUOTE; \
+ continue; \
+ } \
+ c++; \
+ } \
+ } else { \
+ END; \
+ while (*c == ' ') \
+ c++; \
+ } \
+ } \
+ if (quote) {\
+ printk("Warning: unterminated quotation %c\n", quote); \
+ quote = 0; \
+ }
+#define PARSE_ARGS_COUNT(ARGS) PARSE_ARGS(ARGS, argc++, c++, )
+#define PARSE_ARGS_STORE(ARGS) PARSE_ARGS(ARGS, argv[argc++] = c, memmove(c, c + 1, strlen(c + 1) + 1), *c++ = 0)
+
+ PARSE_ARGS_COUNT((char*)start_info.cmd_line);
+#ifdef CONFIG_QEMU_XS_ARGS
+ PARSE_ARGS_COUNT(domargs);
+#endif
+
+ argv = alloca((argc + 1) * sizeof(char *));
+ argv[0] = "main";
+ argc = 1;
+
+ PARSE_ARGS_STORE((char*)start_info.cmd_line)
+#ifdef CONFIG_QEMU_XS_ARGS
+ PARSE_ARGS_STORE(domargs)
+#endif
+
+ argv[argc] = NULL;
+
+ for (i = 0; i < argc; i++)
+ printf("\"%s\" ", argv[i]);
+ printf("\n");
+
+ __libc_init_array();
+ environ = envp;
+ for (i = 0; __CTOR_LIST__[i] != 0; i++)
+ ((void((*)(void)))__CTOR_LIST__[i]) ();
+ tzset();
+
+ exit(main(argc, argv, envp));
+}
+
+void _exit(int ret)
+{
+ int i;
+
+ for (i = 0; __DTOR_LIST__[i] != 0; i++)
+ ((void((*)(void)))__DTOR_LIST__[i]) ();
+ close_all_files();
+ __libc_fini_array();
+ printk("main returned %d\n", ret);
+#if defined(HAVE_LWIP) && defined(CONFIG_NETFRONT)
+ stop_networking();
+#endif
+ stop_kernel();
+ if (!ret) {
+ /* No problem, just shutdown. */
+ struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_poweroff };
+ HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
+ }
+ do_exit();
+}
+
+int app_main(start_info_t *si)
+{
+ printk("main.c: dummy main: start_info=%p\n", si);
+ main_thread = create_thread("main", call_main, si);
+ return 0;
+}
+#endif
--- /dev/null
+#
+# The file contains the common make rules for building mini-os.
+#
+
+debug = y
+
+# Define some default flags.
+# NB. '-Wcast-qual' is nasty, so I omitted it.
+DEF_CFLAGS += -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format -Wno-redundant-decls
+DEF_CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
+DEF_CFLAGS += $(call cc-option,$(CC),-fgnu89-inline)
+DEF_CFLAGS += -Wstrict-prototypes -Wnested-externs -Wpointer-arith -Winline
+DEF_CPPFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION)
+
+DEF_ASFLAGS += -D__ASSEMBLY__
+DEF_LDFLAGS +=
+
+ifeq ($(debug),y)
+DEF_CFLAGS += -g
+#DEF_CFLAGS += -DMM_DEBUG
+#DEF_CFLAGS += -DFS_DEBUG
+#DEF_CFLAGS += -DLIBC_DEBUG
+#DEF_CFLAGS += -DGNT_DEBUG
+#DEF_CFLAGS += -DGNTMAP_DEBUG
+else
+DEF_CFLAGS += -O3
+endif
+
+# Make the headers define our internal stuff
+DEF_CFLAGS += -D__INSIDE_MINIOS__
+
+# Build the CFLAGS and ASFLAGS for compiling and assembling.
+# DEF_... flags are the common mini-os flags,
+# ARCH_... flags may be defined in arch/$(TARGET_ARCH_FAM/rules.mk
+CFLAGS := $(DEF_CFLAGS) $(ARCH_CFLAGS)
+CPPFLAGS := $(DEF_CPPFLAGS) $(ARCH_CPPFLAGS)
+ASFLAGS := $(DEF_ASFLAGS) $(ARCH_ASFLAGS)
+LDFLAGS := $(DEF_LDFLAGS) $(ARCH_LDFLAGS)
+
+# Special build dependencies.
+# Rebuild all after touching this/these file(s)
+EXTRA_DEPS += $(MINI-OS_ROOT)/minios.mk
+EXTRA_DEPS += $(MINI-OS_ROOT)/$(TARGET_ARCH_DIR)/arch.mk
+
+# Find all header files for checking dependencies.
+HDRS := $(wildcard $(MINI-OS_ROOT)/include/*.h)
+HDRS += $(wildcard $(MINI-OS_ROOT)/include/xen/*.h)
+HDRS += $(wildcard $(ARCH_INC)/*.h)
+# For special wanted header directories.
+extra_heads := $(foreach dir,$(EXTRA_INC),$(wildcard $(dir)/*.h))
+HDRS += $(extra_heads)
+
+# Add the special header directories to the include paths.
+override CPPFLAGS := $(CPPFLAGS) $(extra_incl)
+
+# The name of the architecture specific library.
+# This is on x86_32: libx86_32.a
+# $(ARCH_LIB) has to built in the architecture specific directory.
+ARCH_LIB_NAME = $(MINIOS_TARGET_ARCH)
+ARCH_LIB := lib$(ARCH_LIB_NAME).a
+
+# This object contains the entrypoint for startup from Xen.
+# $(HEAD_ARCH_OBJ) has to be built in the architecture specific directory.
+HEAD_ARCH_OBJ := $(MINIOS_TARGET_ARCH).o
+HEAD_OBJ := $(OBJ_DIR)/$(TARGET_ARCH_DIR)/$(HEAD_ARCH_OBJ)
+
+
+$(OBJ_DIR)/%.o: %.c $(HDRS) Makefile $(EXTRA_DEPS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
+
+$(OBJ_DIR)/%.o: %.S $(HDRS) Makefile $(EXTRA_DEPS)
+ $(CC) $(ASFLAGS) $(CPPFLAGS) -c $< -o $@
+
+
+
+
--- /dev/null
+/*
+ ****************************************************************************
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: mm.c
+ * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
+ * Changes: Grzegorz Milos
+ *
+ * Date: Aug 2003, chages Aug 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: memory management related functions
+ * contains buddy page allocator from Xen.
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <mini-os/os.h>
+#include <mini-os/hypervisor.h>
+#include <xen/memory.h>
+#include <mini-os/mm.h>
+#include <mini-os/types.h>
+#include <mini-os/lib.h>
+#include <mini-os/xmalloc.h>
+
+#ifdef MM_DEBUG
+#define DEBUG(_f, _a...) \
+ printk("MINI_OS(file=mm.c, line=%d) " _f "\n", __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...) ((void)0)
+#endif
+
+/*********************
+ * ALLOCATION BITMAP
+ * One bit per page of memory. Bit set => page is allocated.
+ */
+
+static unsigned long *alloc_bitmap;
+#define PAGES_PER_MAPWORD (sizeof(unsigned long) * 8)
+
+#define allocated_in_map(_pn) \
+(alloc_bitmap[(_pn)/PAGES_PER_MAPWORD] & (1UL<<((_pn)&(PAGES_PER_MAPWORD-1))))
+
+/*
+ * Hint regarding bitwise arithmetic in map_{alloc,free}:
+ * -(1<<n) sets all bits >= n.
+ * (1<<n)-1 sets all bits < n.
+ * Variable names in map_{alloc,free}:
+ * *_idx == Index into `alloc_bitmap' array.
+ * *_off == Bit offset within an element of the `alloc_bitmap' array.
+ */
+
+static void map_alloc(unsigned long first_page, unsigned long nr_pages)
+{
+ unsigned long start_off, end_off, curr_idx, end_idx;
+
+ curr_idx = first_page / PAGES_PER_MAPWORD;
+ start_off = first_page & (PAGES_PER_MAPWORD-1);
+ end_idx = (first_page + nr_pages) / PAGES_PER_MAPWORD;
+ end_off = (first_page + nr_pages) & (PAGES_PER_MAPWORD-1);
+
+ if ( curr_idx == end_idx )
+ {
+ alloc_bitmap[curr_idx] |= ((1UL<<end_off)-1) & -(1UL<<start_off);
+ }
+ else
+ {
+ alloc_bitmap[curr_idx] |= -(1UL<<start_off);
+ while ( ++curr_idx < end_idx ) alloc_bitmap[curr_idx] = ~0UL;
+ alloc_bitmap[curr_idx] |= (1UL<<end_off)-1;
+ }
+}
+
+
+static void map_free(unsigned long first_page, unsigned long nr_pages)
+{
+ unsigned long start_off, end_off, curr_idx, end_idx;
+
+ curr_idx = first_page / PAGES_PER_MAPWORD;
+ start_off = first_page & (PAGES_PER_MAPWORD-1);
+ end_idx = (first_page + nr_pages) / PAGES_PER_MAPWORD;
+ end_off = (first_page + nr_pages) & (PAGES_PER_MAPWORD-1);
+
+ if ( curr_idx == end_idx )
+ {
+ alloc_bitmap[curr_idx] &= -(1UL<<end_off) | ((1UL<<start_off)-1);
+ }
+ else
+ {
+ alloc_bitmap[curr_idx] &= (1UL<<start_off)-1;
+ while ( ++curr_idx != end_idx ) alloc_bitmap[curr_idx] = 0;
+ alloc_bitmap[curr_idx] &= -(1UL<<end_off);
+ }
+}
+
+
+
+/*************************
+ * BINARY BUDDY ALLOCATOR
+ */
+
+typedef struct chunk_head_st chunk_head_t;
+typedef struct chunk_tail_st chunk_tail_t;
+
+struct chunk_head_st {
+ chunk_head_t *next;
+ chunk_head_t **pprev;
+ int level;
+};
+
+struct chunk_tail_st {
+ int level;
+};
+
+/* Linked lists of free chunks of different powers-of-two in size. */
+#define FREELIST_SIZE ((sizeof(void*)<<3)-PAGE_SHIFT)
+static chunk_head_t *free_head[FREELIST_SIZE];
+static chunk_head_t free_tail[FREELIST_SIZE];
+#define FREELIST_EMPTY(_l) ((_l)->next == NULL)
+
+#define round_pgdown(_p) ((_p)&PAGE_MASK)
+#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
+
+#ifdef MM_DEBUG
+/*
+ * Prints allocation[0/1] for @nr_pages, starting at @start
+ * address (virtual).
+ */
+USED static void print_allocation(void *start, int nr_pages)
+{
+ unsigned long pfn_start = virt_to_pfn(start);
+ int count;
+ for(count = 0; count < nr_pages; count++)
+ if(allocated_in_map(pfn_start + count)) printk("1");
+ else printk("0");
+
+ printk("\n");
+}
+
+/*
+ * Prints chunks (making them with letters) for @nr_pages starting
+ * at @start (virtual).
+ */
+USED static void print_chunks(void *start, int nr_pages)
+{
+ char chunks[1001], current='A';
+ int order, count;
+ chunk_head_t *head;
+ unsigned long pfn_start = virt_to_pfn(start);
+
+ memset(chunks, (int)'_', 1000);
+ if(nr_pages > 1000)
+ {
+ DEBUG("Can only pring 1000 pages. Increase buffer size.");
+ }
+
+ for(order=0; order < FREELIST_SIZE; order++)
+ {
+ head = free_head[order];
+ while(!FREELIST_EMPTY(head))
+ {
+ for(count = 0; count < 1UL<< head->level; count++)
+ {
+ if(count + virt_to_pfn(head) - pfn_start < 1000)
+ chunks[count + virt_to_pfn(head) - pfn_start] = current;
+ }
+ head = head->next;
+ current++;
+ }
+ }
+ chunks[nr_pages] = '\0';
+ printk("%s\n", chunks);
+}
+#endif
+
+
+/*
+ * Initialise allocator, placing addresses [@min,@max] in free pool.
+ * @min and @max are PHYSICAL addresses.
+ */
+static void init_page_allocator(unsigned long min, unsigned long max)
+{
+ int i;
+ unsigned long range, bitmap_size;
+ chunk_head_t *ch;
+ chunk_tail_t *ct;
+ for ( i = 0; i < FREELIST_SIZE; i++ )
+ {
+ free_head[i] = &free_tail[i];
+ free_tail[i].pprev = &free_head[i];
+ free_tail[i].next = NULL;
+ }
+
+ min = round_pgup (min);
+ max = round_pgdown(max);
+
+ /* Allocate space for the allocation bitmap. */
+ bitmap_size = (max+1) >> (PAGE_SHIFT+3);
+ bitmap_size = round_pgup(bitmap_size);
+ alloc_bitmap = (unsigned long *)to_virt(min);
+ min += bitmap_size;
+ range = max - min;
+
+ /* All allocated by default. */
+ memset(alloc_bitmap, ~0, bitmap_size);
+ /* Free up the memory we've been given to play with. */
+ map_free(PHYS_PFN(min), range>>PAGE_SHIFT);
+
+ /* The buddy lists are addressed in high memory. */
+ min = (unsigned long) to_virt(min);
+ max = (unsigned long) to_virt(max);
+
+ while ( range != 0 )
+ {
+ /*
+ * Next chunk is limited by alignment of min, but also
+ * must not be bigger than remaining range.
+ */
+ for ( i = PAGE_SHIFT; (1UL<<(i+1)) <= range; i++ )
+ if ( min & (1UL<<i) ) break;
+
+
+ ch = (chunk_head_t *)min;
+ min += (1UL<<i);
+ range -= (1UL<<i);
+ ct = (chunk_tail_t *)min-1;
+ i -= PAGE_SHIFT;
+ ch->level = i;
+ ch->next = free_head[i];
+ ch->pprev = &free_head[i];
+ ch->next->pprev = &ch->next;
+ free_head[i] = ch;
+ ct->level = i;
+ }
+}
+
+
+/* Allocate 2^@order contiguous pages. Returns a VIRTUAL address. */
+unsigned long alloc_pages(int order)
+{
+ int i;
+ chunk_head_t *alloc_ch, *spare_ch;
+ chunk_tail_t *spare_ct;
+
+
+ /* Find smallest order which can satisfy the request. */
+ for ( i = order; i < FREELIST_SIZE; i++ ) {
+ if ( !FREELIST_EMPTY(free_head[i]) )
+ break;
+ }
+
+ if ( i == FREELIST_SIZE ) goto no_memory;
+
+ /* Unlink a chunk. */
+ alloc_ch = free_head[i];
+ free_head[i] = alloc_ch->next;
+ alloc_ch->next->pprev = alloc_ch->pprev;
+
+ /* We may have to break the chunk a number of times. */
+ while ( i != order )
+ {
+ /* Split into two equal parts. */
+ i--;
+ spare_ch = (chunk_head_t *)((char *)alloc_ch + (1UL<<(i+PAGE_SHIFT)));
+ spare_ct = (chunk_tail_t *)((char *)spare_ch + (1UL<<(i+PAGE_SHIFT)))-1;
+
+ /* Create new header for spare chunk. */
+ spare_ch->level = i;
+ spare_ch->next = free_head[i];
+ spare_ch->pprev = &free_head[i];
+ spare_ct->level = i;
+
+ /* Link in the spare chunk. */
+ spare_ch->next->pprev = &spare_ch->next;
+ free_head[i] = spare_ch;
+ }
+
+ map_alloc(PHYS_PFN(to_phys(alloc_ch)), 1UL<<order);
+
+ return((unsigned long)alloc_ch);
+
+ no_memory:
+
+ printk("Cannot handle page request order %d!\n", order);
+
+ return 0;
+}
+
+void free_pages(void *pointer, int order)
+{
+ chunk_head_t *freed_ch, *to_merge_ch;
+ chunk_tail_t *freed_ct;
+ unsigned long mask;
+
+ /* First free the chunk */
+ map_free(virt_to_pfn(pointer), 1UL << order);
+
+ /* Create free chunk */
+ freed_ch = (chunk_head_t *)pointer;
+ freed_ct = (chunk_tail_t *)((char *)pointer + (1UL<<(order + PAGE_SHIFT)))-1;
+
+ /* Now, possibly we can conseal chunks together */
+ while(order < FREELIST_SIZE)
+ {
+ mask = 1UL << (order + PAGE_SHIFT);
+ if((unsigned long)freed_ch & mask)
+ {
+ to_merge_ch = (chunk_head_t *)((char *)freed_ch - mask);
+ if(allocated_in_map(virt_to_pfn(to_merge_ch)) ||
+ to_merge_ch->level != order)
+ break;
+
+ /* Merge with predecessor */
+ freed_ch = to_merge_ch;
+ }
+ else
+ {
+ to_merge_ch = (chunk_head_t *)((char *)freed_ch + mask);
+ if(allocated_in_map(virt_to_pfn(to_merge_ch)) ||
+ to_merge_ch->level != order)
+ break;
+
+ /* Merge with successor */
+ freed_ct = (chunk_tail_t *)((char *)to_merge_ch + mask) - 1;
+ }
+
+ /* We are commited to merging, unlink the chunk */
+ *(to_merge_ch->pprev) = to_merge_ch->next;
+ to_merge_ch->next->pprev = to_merge_ch->pprev;
+
+ order++;
+ }
+
+ /* Link the new chunk */
+ freed_ch->level = order;
+ freed_ch->next = free_head[order];
+ freed_ch->pprev = &free_head[order];
+ freed_ct->level = order;
+
+ freed_ch->next->pprev = &freed_ch->next;
+ free_head[order] = freed_ch;
+
+}
+
+int free_physical_pages(xen_pfn_t *mfns, int n)
+{
+ struct xen_memory_reservation reservation;
+
+ set_xen_guest_handle(reservation.extent_start, mfns);
+ reservation.nr_extents = n;
+ reservation.extent_order = 0;
+ reservation.domid = DOMID_SELF;
+ return HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
+}
+
+#ifdef HAVE_LIBC
+void *sbrk(ptrdiff_t increment)
+{
+ unsigned long old_brk = brk;
+ unsigned long new_brk = old_brk + increment;
+
+ if (new_brk > heap_end) {
+ printk("Heap exhausted: %p + %lx = %p > %p\n", old_brk, increment, new_brk, heap_end);
+ return NULL;
+ }
+
+ if (new_brk > heap_mapped) {
+ unsigned long n = (new_brk - heap_mapped + PAGE_SIZE - 1) / PAGE_SIZE;
+ do_map_zero(heap_mapped, n);
+ heap_mapped += n * PAGE_SIZE;
+ }
+
+ brk = new_brk;
+
+ return (void *) old_brk;
+}
+#endif
+
+
+
+void init_mm(void)
+{
+
+ unsigned long start_pfn, max_pfn;
+
+ printk("MM: Init\n");
+
+ arch_init_mm(&start_pfn, &max_pfn);
+ /*
+ * now we can initialise the page allocator
+ */
+ printk("MM: Initialise page allocator for %lx(%lx)-%lx(%lx)\n",
+ (u_long)to_virt(PFN_PHYS(start_pfn)), (u_long)PFN_PHYS(start_pfn),
+ (u_long)to_virt(PFN_PHYS(max_pfn)), (u_long)PFN_PHYS(max_pfn));
+ init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn));
+ printk("MM: done\n");
+
+ arch_init_p2m(max_pfn);
+
+ arch_init_demand_mapping_area(max_pfn);
+}
+
+void fini_mm(void)
+{
+}
+
+void sanity_check(void)
+{
+ int x;
+ chunk_head_t *head;
+
+ for (x = 0; x < FREELIST_SIZE; x++) {
+ for (head = free_head[x]; !FREELIST_EMPTY(head); head = head->next) {
+ ASSERT(!allocated_in_map(virt_to_pfn(head)));
+ if (head->next)
+ ASSERT(head->next->pprev == &head->next);
+ }
+ if (free_head[x]) {
+ ASSERT(free_head[x]->pprev == &free_head[x]);
+ }
+ }
+}
--- /dev/null
+/* Minimal network driver for Mini-OS.
+ * Copyright (c) 2006-2007 Jacob Gorm Hansen, University of Copenhagen.
+ * Based on netfront.c from Xen Linux.
+ *
+ * Does not handle fragments or extras.
+ */
+
+#include <mini-os/os.h>
+#include <mini-os/xenbus.h>
+#include <mini-os/events.h>
+#include <errno.h>
+#include <xen/io/netif.h>
+#include <mini-os/gnttab.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/time.h>
+#include <mini-os/netfront.h>
+#include <mini-os/lib.h>
+#include <mini-os/semaphore.h>
+
+DECLARE_WAIT_QUEUE_HEAD(netfront_queue);
+
+#ifdef HAVE_LIBC
+#define NETIF_SELECT_RX ((void*)-1)
+#endif
+
+
+
+#define NET_TX_RING_SIZE __CONST_RING_SIZE(netif_tx, PAGE_SIZE)
+#define NET_RX_RING_SIZE __CONST_RING_SIZE(netif_rx, PAGE_SIZE)
+#define GRANT_INVALID_REF 0
+
+
+struct net_buffer {
+ void* page;
+ grant_ref_t gref;
+};
+
+struct netfront_dev {
+ domid_t dom;
+
+ unsigned short tx_freelist[NET_TX_RING_SIZE + 1];
+ struct semaphore tx_sem;
+
+ struct net_buffer rx_buffers[NET_RX_RING_SIZE];
+ struct net_buffer tx_buffers[NET_TX_RING_SIZE];
+
+ struct netif_tx_front_ring tx;
+ struct netif_rx_front_ring rx;
+ grant_ref_t tx_ring_ref;
+ grant_ref_t rx_ring_ref;
+ evtchn_port_t evtchn;
+
+ char *nodename;
+ char *backend;
+ char *mac;
+
+ xenbus_event_queue events;
+
+#ifdef HAVE_LIBC
+ int fd;
+ unsigned char *data;
+ size_t len;
+ size_t rlen;
+#endif
+
+ void (*netif_rx)(unsigned char* data, int len);
+};
+
+void init_rx_buffers(struct netfront_dev *dev);
+
+static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist)
+{
+ freelist[id + 1] = freelist[0];
+ freelist[0] = id;
+}
+
+static inline unsigned short get_id_from_freelist(unsigned short* freelist)
+{
+ unsigned int id = freelist[0];
+ freelist[0] = freelist[id + 1];
+ return id;
+}
+
+__attribute__((weak)) void netif_rx(unsigned char* data,int len)
+{
+ printk("%d bytes incoming at %p\n",len,data);
+}
+
+__attribute__((weak)) void net_app_main(void*si,unsigned char*mac) {}
+
+static inline int xennet_rxidx(RING_IDX idx)
+{
+ return idx & (NET_RX_RING_SIZE - 1);
+}
+
+void network_rx(struct netfront_dev *dev)
+{
+ RING_IDX rp,cons,req_prod;
+ int nr_consumed, more, i, notify;
+#ifdef HAVE_LIBC
+ int some;
+#endif
+
+ nr_consumed = 0;
+moretodo:
+ rp = dev->rx.sring->rsp_prod;
+ rmb(); /* Ensure we see queued responses up to 'rp'. */
+
+#ifdef HAVE_LIBC
+ some = 0;
+#endif
+ for (cons = dev->rx.rsp_cons; cons != rp; nr_consumed++, cons++)
+ {
+ struct net_buffer* buf;
+ unsigned char* page;
+ int id;
+
+ struct netif_rx_response *rx = RING_GET_RESPONSE(&dev->rx, cons);
+
+ id = rx->id;
+ BUG_ON(id >= NET_RX_RING_SIZE);
+
+ buf = &dev->rx_buffers[id];
+ page = (unsigned char*)buf->page;
+ gnttab_end_access(buf->gref);
+
+ if (rx->status > NETIF_RSP_NULL)
+ {
+#ifdef HAVE_LIBC
+ if (dev->netif_rx == NETIF_SELECT_RX) {
+ int len = rx->status;
+ ASSERT(current == main_thread);
+ if (len > dev->len)
+ len = dev->len;
+ memcpy(dev->data, page+rx->offset, len);
+ dev->rlen = len;
+ some = 1;
+ break;
+ } else
+#endif
+ dev->netif_rx(page+rx->offset,rx->status);
+ }
+ }
+ dev->rx.rsp_cons=cons;
+
+ RING_FINAL_CHECK_FOR_RESPONSES(&dev->rx,more);
+#ifdef HAVE_LIBC
+ if(more && !some) goto moretodo;
+#else
+ if(more) goto moretodo;
+#endif
+
+ req_prod = dev->rx.req_prod_pvt;
+
+ for(i=0; i<nr_consumed; i++)
+ {
+ int id = xennet_rxidx(req_prod + i);
+ netif_rx_request_t *req = RING_GET_REQUEST(&dev->rx, req_prod + i);
+ struct net_buffer* buf = &dev->rx_buffers[id];
+ void* page = buf->page;
+
+ /* We are sure to have free gnttab entries since they got released above */
+ buf->gref = req->gref =
+ gnttab_grant_access(dev->dom,virt_to_mfn(page),0);
+
+ req->id = id;
+ }
+
+ wmb();
+
+ dev->rx.req_prod_pvt = req_prod + i;
+
+ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->rx, notify);
+ if (notify)
+ notify_remote_via_evtchn(dev->evtchn);
+
+}
+
+void network_tx_buf_gc(struct netfront_dev *dev)
+{
+
+
+ RING_IDX cons, prod;
+ unsigned short id;
+
+ do {
+ prod = dev->tx.sring->rsp_prod;
+ rmb(); /* Ensure we see responses up to 'rp'. */
+
+ for (cons = dev->tx.rsp_cons; cons != prod; cons++)
+ {
+ struct netif_tx_response *txrsp;
+ struct net_buffer *buf;
+
+ txrsp = RING_GET_RESPONSE(&dev->tx, cons);
+ if (txrsp->status == NETIF_RSP_NULL)
+ continue;
+
+ if (txrsp->status == NETIF_RSP_ERROR)
+ printk("packet error\n");
+
+ id = txrsp->id;
+ BUG_ON(id >= NET_TX_RING_SIZE);
+ buf = &dev->tx_buffers[id];
+ gnttab_end_access(buf->gref);
+ buf->gref=GRANT_INVALID_REF;
+
+ add_id_to_freelist(id,dev->tx_freelist);
+ up(&dev->tx_sem);
+ }
+
+ dev->tx.rsp_cons = prod;
+
+ /*
+ * Set a new event, then check for race with update of tx_cons.
+ * Note that it is essential to schedule a callback, no matter
+ * how few tx_buffers are pending. Even if there is space in the
+ * transmit ring, higher layers may be blocked because too much
+ * data is outstanding: in such cases notification from Xen is
+ * likely to be the only kick that we'll get.
+ */
+ dev->tx.sring->rsp_event =
+ prod + ((dev->tx.sring->req_prod - prod) >> 1) + 1;
+ mb();
+ } while ((cons == prod) && (prod != dev->tx.sring->rsp_prod));
+
+
+}
+
+void netfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+ int flags;
+ struct netfront_dev *dev = data;
+
+ local_irq_save(flags);
+
+ network_tx_buf_gc(dev);
+ network_rx(dev);
+
+ local_irq_restore(flags);
+}
+
+#ifdef HAVE_LIBC
+void netfront_select_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+ int flags;
+ struct netfront_dev *dev = data;
+ int fd = dev->fd;
+
+ local_irq_save(flags);
+ network_tx_buf_gc(dev);
+ local_irq_restore(flags);
+
+ if (fd != -1)
+ files[fd].read = 1;
+ wake_up(&netfront_queue);
+}
+#endif
+
+static void free_netfront(struct netfront_dev *dev)
+{
+ int i;
+
+ for(i=0;i<NET_TX_RING_SIZE;i++)
+ down(&dev->tx_sem);
+
+ mask_evtchn(dev->evtchn);
+
+ free(dev->mac);
+ free(dev->backend);
+
+ gnttab_end_access(dev->rx_ring_ref);
+ gnttab_end_access(dev->tx_ring_ref);
+
+ free_page(dev->rx.sring);
+ free_page(dev->tx.sring);
+
+ unbind_evtchn(dev->evtchn);
+
+ for(i=0;i<NET_RX_RING_SIZE;i++) {
+ gnttab_end_access(dev->rx_buffers[i].gref);
+ free_page(dev->rx_buffers[i].page);
+ }
+
+ for(i=0;i<NET_TX_RING_SIZE;i++)
+ if (dev->tx_buffers[i].page)
+ free_page(dev->tx_buffers[i].page);
+
+ free(dev->nodename);
+ free(dev);
+}
+
+struct netfront_dev *init_netfront(char *_nodename, void (*thenetif_rx)(unsigned char* data, int len), unsigned char rawmac[6], char **ip)
+{
+ xenbus_transaction_t xbt;
+ char* err;
+ char* message=NULL;
+ struct netif_tx_sring *txs;
+ struct netif_rx_sring *rxs;
+ int retry=0;
+ int i;
+ char* msg = NULL;
+ char nodename[256];
+ char path[256];
+ struct netfront_dev *dev;
+ static int netfrontends = 0;
+
+ if (!_nodename)
+ snprintf(nodename, sizeof(nodename), "device/vif/%d", netfrontends);
+ else {
+ strncpy(nodename, _nodename, sizeof(nodename) - 1);
+ nodename[sizeof(nodename) - 1] = 0;
+ }
+ netfrontends++;
+
+ if (!thenetif_rx)
+ thenetif_rx = netif_rx;
+
+ printk("************************ NETFRONT for %s **********\n\n\n", nodename);
+
+ dev = malloc(sizeof(*dev));
+ memset(dev, 0, sizeof(*dev));
+ dev->nodename = strdup(nodename);
+#ifdef HAVE_LIBC
+ dev->fd = -1;
+#endif
+
+ printk("net TX ring size %d\n", NET_TX_RING_SIZE);
+ printk("net RX ring size %d\n", NET_RX_RING_SIZE);
+ init_SEMAPHORE(&dev->tx_sem, NET_TX_RING_SIZE);
+ for(i=0;i<NET_TX_RING_SIZE;i++)
+ {
+ add_id_to_freelist(i,dev->tx_freelist);
+ dev->tx_buffers[i].page = NULL;
+ }
+
+ for(i=0;i<NET_RX_RING_SIZE;i++)
+ {
+ /* TODO: that's a lot of memory */
+ dev->rx_buffers[i].page = (char*)alloc_page();
+ }
+
+ snprintf(path, sizeof(path), "%s/backend-id", nodename);
+ dev->dom = xenbus_read_integer(path);
+#ifdef HAVE_LIBC
+ if (thenetif_rx == NETIF_SELECT_RX)
+ evtchn_alloc_unbound(dev->dom, netfront_select_handler, dev, &dev->evtchn);
+ else
+#endif
+ evtchn_alloc_unbound(dev->dom, netfront_handler, dev, &dev->evtchn);
+
+ txs = (struct netif_tx_sring *) alloc_page();
+ rxs = (struct netif_rx_sring *) alloc_page();
+ memset(txs,0,PAGE_SIZE);
+ memset(rxs,0,PAGE_SIZE);
+
+
+ SHARED_RING_INIT(txs);
+ SHARED_RING_INIT(rxs);
+ FRONT_RING_INIT(&dev->tx, txs, PAGE_SIZE);
+ FRONT_RING_INIT(&dev->rx, rxs, PAGE_SIZE);
+
+ dev->tx_ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(txs),0);
+ dev->rx_ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(rxs),0);
+
+ init_rx_buffers(dev);
+
+ dev->netif_rx = thenetif_rx;
+
+ dev->events = NULL;
+
+again:
+ err = xenbus_transaction_start(&xbt);
+ if (err) {
+ printk("starting transaction\n");
+ free(err);
+ }
+
+ err = xenbus_printf(xbt, nodename, "tx-ring-ref","%u",
+ dev->tx_ring_ref);
+ if (err) {
+ message = "writing tx ring-ref";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(xbt, nodename, "rx-ring-ref","%u",
+ dev->rx_ring_ref);
+ if (err) {
+ message = "writing rx ring-ref";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(xbt, nodename,
+ "event-channel", "%u", dev->evtchn);
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+
+ err = xenbus_printf(xbt, nodename, "request-rx-copy", "%u", 1);
+
+ if (err) {
+ message = "writing request-rx-copy";
+ goto abort_transaction;
+ }
+
+ snprintf(path, sizeof(path), "%s/state", nodename);
+ err = xenbus_switch_state(xbt, path, XenbusStateConnected);
+ if (err) {
+ message = "switching state";
+ goto abort_transaction;
+ }
+
+ err = xenbus_transaction_end(xbt, 0, &retry);
+ free(err);
+ if (retry) {
+ goto again;
+ printk("completing transaction\n");
+ }
+
+ goto done;
+
+abort_transaction:
+ free(err);
+ err = xenbus_transaction_end(xbt, 1, &retry);
+ printk("Abort transaction %s\n", message);
+ goto error;
+
+done:
+
+ snprintf(path, sizeof(path), "%s/backend", nodename);
+ msg = xenbus_read(XBT_NIL, path, &dev->backend);
+ snprintf(path, sizeof(path), "%s/mac", nodename);
+ msg = xenbus_read(XBT_NIL, path, &dev->mac);
+
+ if ((dev->backend == NULL) || (dev->mac == NULL)) {
+ printk("%s: backend/mac failed\n", __func__);
+ goto error;
+ }
+
+ printk("backend at %s\n",dev->backend);
+ printk("mac is %s\n",dev->mac);
+
+ {
+ XenbusState state;
+ char path[strlen(dev->backend) + strlen("/state") + 1];
+ snprintf(path, sizeof(path), "%s/state", dev->backend);
+
+ xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
+
+ err = NULL;
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateConnected)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ if (state != XenbusStateConnected) {
+ printk("backend not avalable, state=%d\n", state);
+ xenbus_unwatch_path_token(XBT_NIL, path, path);
+ goto error;
+ }
+
+ if (ip) {
+ snprintf(path, sizeof(path), "%s/ip", dev->backend);
+ xenbus_read(XBT_NIL, path, ip);
+ }
+ }
+
+ printk("**************************\n");
+
+ unmask_evtchn(dev->evtchn);
+
+ /* Special conversion specifier 'hh' needed for __ia64__. Without
+ this mini-os panics with 'Unaligned reference'. */
+ if (rawmac)
+ sscanf(dev->mac,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+ &rawmac[0],
+ &rawmac[1],
+ &rawmac[2],
+ &rawmac[3],
+ &rawmac[4],
+ &rawmac[5]);
+
+ return dev;
+error:
+ free(msg);
+ free(err);
+ free_netfront(dev);
+ return NULL;
+}
+
+#ifdef HAVE_LIBC
+int netfront_tap_open(char *nodename) {
+ struct netfront_dev *dev;
+
+ dev = init_netfront(nodename, NETIF_SELECT_RX, NULL, NULL);
+ if (!dev) {
+ printk("TAP open failed\n");
+ errno = EIO;
+ return -1;
+ }
+ dev->fd = alloc_fd(FTYPE_TAP);
+ printk("tap_open(%s) -> %d\n", nodename, dev->fd);
+ files[dev->fd].tap.dev = dev;
+ return dev->fd;
+}
+#endif
+
+void shutdown_netfront(struct netfront_dev *dev)
+{
+ char* err = NULL, *err2;
+ XenbusState state;
+
+ char path[strlen(dev->backend) + strlen("/state") + 1];
+ char nodename[strlen(dev->nodename) + strlen("/request-rx-copy") + 1];
+
+ printk("close network: backend at %s\n",dev->backend);
+
+ snprintf(path, sizeof(path), "%s/state", dev->backend);
+ snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
+ printk("shutdown_netfront: error changing state to %d: %s\n",
+ XenbusStateClosing, err);
+ goto close;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateClosing)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ free(err);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
+ printk("shutdown_netfront: error changing state to %d: %s\n",
+ XenbusStateClosed, err);
+ goto close;
+ }
+ state = xenbus_read_integer(path);
+ while (state < XenbusStateClosed) {
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ free(err);
+ }
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
+ printk("shutdown_netfront: error changing state to %d: %s\n",
+ XenbusStateInitialising, err);
+ goto close;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+
+close:
+ free(err);
+ err2 = xenbus_unwatch_path_token(XBT_NIL, path, path);
+ free(err2);
+
+ snprintf(nodename, sizeof(nodename), "%s/tx-ring-ref", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+ snprintf(nodename, sizeof(nodename), "%s/rx-ring-ref", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+ snprintf(nodename, sizeof(nodename), "%s/event-channel", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+ snprintf(nodename, sizeof(nodename), "%s/request-rx-copy", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+
+ if (!err)
+ free_netfront(dev);
+}
+
+
+void init_rx_buffers(struct netfront_dev *dev)
+{
+ int i, requeue_idx;
+ netif_rx_request_t *req;
+ int notify;
+
+ /* Rebuild the RX buffer freelist and the RX ring itself. */
+ for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++)
+ {
+ struct net_buffer* buf = &dev->rx_buffers[requeue_idx];
+ req = RING_GET_REQUEST(&dev->rx, requeue_idx);
+
+ buf->gref = req->gref =
+ gnttab_grant_access(dev->dom,virt_to_mfn(buf->page),0);
+
+ req->id = requeue_idx;
+
+ requeue_idx++;
+ }
+
+ dev->rx.req_prod_pvt = requeue_idx;
+
+ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->rx, notify);
+
+ if (notify)
+ notify_remote_via_evtchn(dev->evtchn);
+
+ dev->rx.sring->rsp_event = dev->rx.rsp_cons + 1;
+}
+
+
+void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len)
+{
+ int flags;
+ struct netif_tx_request *tx;
+ RING_IDX i;
+ int notify;
+ unsigned short id;
+ struct net_buffer* buf;
+ void* page;
+
+ BUG_ON(len > PAGE_SIZE);
+
+ down(&dev->tx_sem);
+
+ local_irq_save(flags);
+ id = get_id_from_freelist(dev->tx_freelist);
+ local_irq_restore(flags);
+
+ buf = &dev->tx_buffers[id];
+ page = buf->page;
+ if (!page)
+ page = buf->page = (char*) alloc_page();
+
+ i = dev->tx.req_prod_pvt;
+ tx = RING_GET_REQUEST(&dev->tx, i);
+
+ memcpy(page,data,len);
+
+ buf->gref =
+ tx->gref = gnttab_grant_access(dev->dom,virt_to_mfn(page),1);
+
+ tx->offset=0;
+ tx->size = len;
+ tx->flags=0;
+ tx->id = id;
+ dev->tx.req_prod_pvt = i + 1;
+
+ wmb();
+
+ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->tx, notify);
+
+ if(notify) notify_remote_via_evtchn(dev->evtchn);
+
+ local_irq_save(flags);
+ network_tx_buf_gc(dev);
+ local_irq_restore(flags);
+}
+
+#ifdef HAVE_LIBC
+ssize_t netfront_receive(struct netfront_dev *dev, unsigned char *data, size_t len)
+{
+ unsigned long flags;
+ int fd = dev->fd;
+ ASSERT(current == main_thread);
+
+ dev->rlen = 0;
+ dev->data = data;
+ dev->len = len;
+
+ local_irq_save(flags);
+ network_rx(dev);
+ if (!dev->rlen && fd != -1)
+ /* No data for us, make select stop returning */
+ files[fd].read = 0;
+ /* Before re-enabling the interrupts, in case a packet just arrived in the
+ * meanwhile. */
+ local_irq_restore(flags);
+
+ dev->data = NULL;
+ dev->len = 0;
+
+ return dev->rlen;
+}
+#endif
--- /dev/null
+/* Minimal PCI driver for Mini-OS.
+ * Copyright (c) 2007-2008 Samuel Thibault.
+ * Based on blkfront.c.
+ */
+
+#include <string.h>
+#include <mini-os/os.h>
+#include <mini-os/lib.h>
+#include <mini-os/xenbus.h>
+#include <mini-os/events.h>
+#include <errno.h>
+#include <mini-os/gnttab.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/wait.h>
+#include <mini-os/pcifront.h>
+#include <mini-os/sched.h>
+
+#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+
+DECLARE_WAIT_QUEUE_HEAD(pcifront_queue);
+static struct pcifront_dev *pcidev;
+
+struct pcifront_dev {
+ domid_t dom;
+
+ struct xen_pci_sharedinfo *info;
+ grant_ref_t info_ref;
+ evtchn_port_t evtchn;
+
+ char *nodename;
+ char *backend;
+
+ xenbus_event_queue events;
+};
+
+void pcifront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+ wake_up(&pcifront_queue);
+}
+
+static void free_pcifront(struct pcifront_dev *dev)
+{
+ if (!dev)
+ dev = pcidev;
+
+ mask_evtchn(dev->evtchn);
+
+ gnttab_end_access(dev->info_ref);
+ free_page(dev->info);
+
+ unbind_evtchn(dev->evtchn);
+
+ free(dev->backend);
+ free(dev->nodename);
+ free(dev);
+}
+
+void pcifront_watches(void *opaque)
+{
+ XenbusState state;
+ char *err = NULL, *msg = NULL;
+ char *be_path, *be_state;
+ char* nodename = opaque ? opaque : "device/pci/0";
+ char path[strlen(nodename) + 9];
+ char fe_state[strlen(nodename) + 7];
+ xenbus_event_queue events = NULL;
+
+ snprintf(path, sizeof(path), "%s/backend", nodename);
+ snprintf(fe_state, sizeof(fe_state), "%s/state", nodename);
+
+ while (1) {
+ printk("pcifront_watches: waiting for backend path to appear %s\n", path);
+ xenbus_watch_path_token(XBT_NIL, path, path, &events);
+ while ((err = xenbus_read(XBT_NIL, path, &be_path)) != NULL) {
+ free(err);
+ xenbus_wait_for_watch(&events);
+ }
+ xenbus_unwatch_path_token(XBT_NIL, path, path);
+ printk("pcifront_watches: waiting for backend to get into the right state %s\n", be_path);
+ be_state = (char *) malloc(strlen(be_path) + 7);
+ snprintf(be_state, strlen(be_path) + 7, "%s/state", be_path);
+ xenbus_watch_path_token(XBT_NIL, be_state, be_state, &events);
+ while ((err = xenbus_read(XBT_NIL, be_state, &msg)) != NULL || msg[0] > '4') {
+ free(msg);
+ free(err);
+ xenbus_wait_for_watch(&events);
+ }
+ xenbus_unwatch_path_token(XBT_NIL, be_state, be_state);
+ if (init_pcifront(NULL) == NULL) {
+ free(be_state);
+ free(be_path);
+ continue;
+ }
+ xenbus_watch_path_token(XBT_NIL, be_state, be_state, &events);
+ state = XenbusStateConnected;
+ printk("pcifront_watches: waiting for backend events %s\n", be_state);
+ while ((err = xenbus_wait_for_state_change(be_state, &state, &events)) == NULL &&
+ (err = xenbus_read(XBT_NIL, pcidev->backend, &msg)) == NULL) {
+ free(msg);
+ printk("pcifront_watches: backend state changed: %s %d\n", be_state, state);
+ if (state == XenbusStateReconfiguring) {
+ printk("pcifront_watches: writing %s %d\n", fe_state, XenbusStateReconfiguring);
+ if ((err = xenbus_switch_state(XBT_NIL, fe_state, XenbusStateReconfiguring)) != NULL) {
+ printk("pcifront_watches: error changing state to %d: %s\n",
+ XenbusStateReconfiguring, err);
+ if (!strcmp(err, "ENOENT")) {
+ xenbus_write(XBT_NIL, fe_state, "7");
+ free(err);
+ }
+ }
+ } else if (state == XenbusStateReconfigured) {
+ printk("pcifront_watches: writing %s %d\n", fe_state, XenbusStateConnected);
+ printk("pcifront_watches: changing state to %d\n", XenbusStateConnected);
+ if ((err = xenbus_switch_state(XBT_NIL, fe_state, XenbusStateConnected)) != NULL) {
+ printk("pcifront_watches: error changing state to %d: %s\n",
+ XenbusStateConnected, err);
+ if (!strcmp(err, "ENOENT")) {
+ xenbus_write(XBT_NIL, fe_state, "4");
+ free(err);
+ }
+ }
+ } else if (state == XenbusStateClosing)
+ break;
+ }
+ if (err) {
+ printk("pcifront_watches: done waiting err=%s\n", err);
+ free(err);
+ } else
+ printk("pcifront_watches: done waiting\n");
+ err = xenbus_unwatch_path_token(XBT_NIL, be_state, be_state);
+ shutdown_pcifront(pcidev);
+ free(be_state);
+ free(be_path);
+ free(err);
+ pcidev = NULL;
+ }
+
+ xenbus_unwatch_path_token(XBT_NIL, path, path);
+}
+
+struct pcifront_dev *init_pcifront(char *_nodename)
+{
+ xenbus_transaction_t xbt;
+ char* err;
+ char* message=NULL;
+ int retry=0;
+ char* msg = NULL;
+ char* nodename = _nodename ? _nodename : "device/pci/0";
+ int dom;
+
+ struct pcifront_dev *dev;
+
+ char path[strlen(nodename) + strlen("/backend-id") + 1];
+
+ if (!_nodename && pcidev)
+ return pcidev;
+
+ printk("******************* PCIFRONT for %s **********\n\n\n", nodename);
+
+ snprintf(path, sizeof(path), "%s/backend-id", nodename);
+ dom = xenbus_read_integer(path);
+ if (dom == -1) {
+ printk("no backend\n");
+ return NULL;
+ }
+
+ dev = malloc(sizeof(*dev));
+ memset(dev, 0, sizeof(*dev));
+ dev->nodename = strdup(nodename);
+ dev->dom = dom;
+
+ evtchn_alloc_unbound(dev->dom, pcifront_handler, dev, &dev->evtchn);
+
+ dev->info = (struct xen_pci_sharedinfo*) alloc_page();
+ memset(dev->info,0,PAGE_SIZE);
+
+ dev->info_ref = gnttab_grant_access(dev->dom,virt_to_mfn(dev->info),0);
+
+ dev->events = NULL;
+
+again:
+ err = xenbus_transaction_start(&xbt);
+ if (err) {
+ printk("starting transaction\n");
+ free(err);
+ }
+
+ err = xenbus_printf(xbt, nodename, "pci-op-ref","%u",
+ dev->info_ref);
+ if (err) {
+ message = "writing pci-op-ref";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(xbt, nodename,
+ "event-channel", "%u", dev->evtchn);
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(xbt, nodename,
+ "magic", XEN_PCI_MAGIC);
+ if (err) {
+ message = "writing magic";
+ goto abort_transaction;
+ }
+
+ snprintf(path, sizeof(path), "%s/state", nodename);
+ err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
+ if (err) {
+ message = "switching state";
+ goto abort_transaction;
+ }
+
+ err = xenbus_transaction_end(xbt, 0, &retry);
+ free(err);
+ if (retry) {
+ goto again;
+ printk("completing transaction\n");
+ }
+
+ goto done;
+
+abort_transaction:
+ free(err);
+ err = xenbus_transaction_end(xbt, 1, &retry);
+ printk("Abort transaction %s\n", message);
+ goto error;
+
+done:
+
+ snprintf(path, sizeof(path), "%s/backend", nodename);
+ msg = xenbus_read(XBT_NIL, path, &dev->backend);
+ if (msg) {
+ printk("Error %s when reading the backend path %s\n", msg, path);
+ goto error;
+ }
+
+ printk("backend at %s\n", dev->backend);
+
+ {
+ char path[strlen(dev->backend) + strlen("/state") + 1];
+ char frontpath[strlen(nodename) + strlen("/state") + 1];
+ XenbusState state;
+ snprintf(path, sizeof(path), "%s/state", dev->backend);
+
+ xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
+
+ err = NULL;
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateConnected)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ if (state != XenbusStateConnected) {
+ printk("backend not avalable, state=%d\n", state);
+ free(err);
+ err = xenbus_unwatch_path_token(XBT_NIL, path, path);
+ goto error;
+ }
+
+ snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
+ if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
+ != NULL) {
+ printk("error switching state %s\n", err);
+ free(err);
+ err = xenbus_unwatch_path_token(XBT_NIL, path, path);
+ goto error;
+ }
+ }
+ unmask_evtchn(dev->evtchn);
+
+ printk("**************************\n");
+
+ if (!_nodename)
+ pcidev = dev;
+
+ return dev;
+
+error:
+ free(msg);
+ free(err);
+ free_pcifront(dev);
+ return NULL;
+}
+
+void pcifront_scan(struct pcifront_dev *dev, void (*func)(unsigned int domain, unsigned int bus, unsigned slot, unsigned int fun))
+{
+ char *path;
+ int i, n, len;
+ char *s, *msg = NULL;
+ unsigned int domain, bus, slot, fun;
+
+ if (!dev)
+ dev = pcidev;
+ if (!dev) {
+ printk("pcifront_scan: device or bus\n");
+ return;
+ }
+
+ len = strlen(dev->backend) + 1 + 5 + 10 + 1;
+ path = (char *) malloc(len);
+ snprintf(path, len, "%s/num_devs", dev->backend);
+ n = xenbus_read_integer(path);
+
+ for (i = 0; i < n; i++) {
+ snprintf(path, len, "%s/dev-%d", dev->backend, i);
+ msg = xenbus_read(XBT_NIL, path, &s);
+ if (msg) {
+ printk("Error %s when reading the PCI root name at %s\n", msg, path);
+ free(msg);
+ continue;
+ }
+
+ if (sscanf(s, "%x:%x:%x.%x", &domain, &bus, &slot, &fun) != 4) {
+ printk("\"%s\" does not look like a PCI device address\n", s);
+ free(s);
+ continue;
+ }
+ free(s);
+
+ if (func)
+ func(domain, bus, slot, fun);
+ }
+ free(path);
+}
+
+void shutdown_pcifront(struct pcifront_dev *dev)
+{
+ char* err = NULL, *err2;
+ XenbusState state;
+
+ char path[strlen(dev->backend) + strlen("/state") + 1];
+ char nodename[strlen(dev->nodename) + strlen("/event-channel") + 1];
+
+ printk("close pci: backend at %s\n",dev->backend);
+
+ snprintf(path, sizeof(path), "%s/state", dev->backend);
+ snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
+ printk("shutdown_pcifront: error changing state to %d: %s\n",
+ XenbusStateClosing, err);
+ goto close_pcifront;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateClosing)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ free(err);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
+ printk("shutdown_pcifront: error changing state to %d: %s\n",
+ XenbusStateClosed, err);
+ goto close_pcifront;
+ }
+ state = xenbus_read_integer(path);
+ while (state < XenbusStateClosed) {
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ free(err);
+ }
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
+ printk("shutdown_pcifront: error changing state to %d: %s\n",
+ XenbusStateInitialising, err);
+ goto close_pcifront;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+
+close_pcifront:
+ free(err);
+ err2 = xenbus_unwatch_path_token(XBT_NIL, path, path);
+ free(err2);
+
+ snprintf(nodename, sizeof(nodename), "%s/info-ref", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+ snprintf(nodename, sizeof(nodename), "%s/event-channel", dev->nodename);
+ err2 = xenbus_rm(XBT_NIL, nodename);
+ free(err2);
+
+ if (!err)
+ free_pcifront(dev);
+}
+
+int pcifront_physical_to_virtual (struct pcifront_dev *dev,
+ unsigned int *dom,
+ unsigned int *bus,
+ unsigned int *slot,
+ unsigned int *fun)
+{
+ /* FIXME: the buffer sizing is a little lazy here. 10 extra bytes
+ should be enough to hold the paths we need to construct, even
+ if the number of devices is large */
+ char path[strlen(dev->backend) + strlen("/num_devs") + 10 + 1];
+ int i, n;
+ char *s, *msg = NULL;
+ unsigned int dom1, bus1, slot1, fun1;
+
+ if (!dev)
+ dev = pcidev;
+
+ snprintf(path, sizeof(path), "%s/num_devs", dev->backend);
+ n = xenbus_read_integer(path);
+
+ for (i = 0; i < n; i++) {
+ snprintf(path, sizeof(path), "%s/dev-%d", dev->backend, i);
+ msg = xenbus_read(XBT_NIL, path, &s);
+ if (msg) {
+ printk("Error %s when reading the PCI root name at %s\n", msg, path);
+ free(msg);
+ continue;
+ }
+
+ if (sscanf(s, "%x:%x:%x.%x", &dom1, &bus1, &slot1, &fun1) != 4) {
+ printk("\"%s\" does not look like a PCI device address\n", s);
+ free(s);
+ continue;
+ }
+ free(s);
+
+ if (dom1 == *dom && bus1 == *bus && slot1 == *slot && fun1 == *fun) {
+ snprintf(path, sizeof(path), "%s/vdev-%d", dev->backend, i);
+ msg = xenbus_read(XBT_NIL, path, &s);
+ if (msg) {
+ printk("Error %s when reading the PCI root name at %s\n", msg, path);
+ continue;
+ }
+
+ if (sscanf(s, "%x:%x:%x.%x", dom, bus, slot, fun) != 4) {
+ printk("\"%s\" does not look like a PCI device address\n", s);
+ free(s);
+ continue;
+ }
+ free(s);
+
+ return 0;
+ }
+ }
+ return -1;
+}
+
+void pcifront_op(struct pcifront_dev *dev, struct xen_pci_op *op)
+{
+ if (!dev)
+ dev = pcidev;
+ dev->info->op = *op;
+ /* Make sure info is written before the flag */
+ wmb();
+ set_bit(_XEN_PCIF_active, (void*) &dev->info->flags);
+ notify_remote_via_evtchn(dev->evtchn);
+
+ wait_event(pcifront_queue, !test_bit(_XEN_PCIF_active, (void*) &dev->info->flags));
+
+ /* Make sure flag is read before info */
+ rmb();
+ *op = dev->info->op;
+}
+
+int pcifront_conf_read(struct pcifront_dev *dev,
+ unsigned int dom,
+ unsigned int bus, unsigned int slot, unsigned int fun,
+ unsigned int off, unsigned int size, unsigned int *val)
+{
+ struct xen_pci_op op;
+
+ if (!dev)
+ dev = pcidev;
+ if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
+ return XEN_PCI_ERR_dev_not_found;
+ memset(&op, 0, sizeof(op));
+
+ op.cmd = XEN_PCI_OP_conf_read;
+ op.domain = dom;
+ op.bus = bus;
+ op.devfn = PCI_DEVFN(slot, fun);
+ op.offset = off;
+ op.size = size;
+
+ pcifront_op(dev, &op);
+
+ if (op.err)
+ return op.err;
+
+ *val = op.value;
+
+ return 0;
+}
+
+int pcifront_conf_write(struct pcifront_dev *dev,
+ unsigned int dom,
+ unsigned int bus, unsigned int slot, unsigned int fun,
+ unsigned int off, unsigned int size, unsigned int val)
+{
+ struct xen_pci_op op;
+
+ if (!dev)
+ dev = pcidev;
+ if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
+ return XEN_PCI_ERR_dev_not_found;
+ memset(&op, 0, sizeof(op));
+
+ op.cmd = XEN_PCI_OP_conf_write;
+ op.domain = dom;
+ op.bus = bus;
+ op.devfn = PCI_DEVFN(slot, fun);
+ op.offset = off;
+ op.size = size;
+
+ op.value = val;
+
+ pcifront_op(dev, &op);
+
+ return op.err;
+}
+
+int pcifront_enable_msi(struct pcifront_dev *dev,
+ unsigned int dom,
+ unsigned int bus, unsigned int slot, unsigned int fun)
+{
+ struct xen_pci_op op;
+
+ if (!dev)
+ dev = pcidev;
+ if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
+ return XEN_PCI_ERR_dev_not_found;
+ memset(&op, 0, sizeof(op));
+
+ op.cmd = XEN_PCI_OP_enable_msi;
+ op.domain = dom;
+ op.bus = bus;
+ op.devfn = PCI_DEVFN(slot, fun);
+
+ pcifront_op(dev, &op);
+
+ if (op.err)
+ return op.err;
+ else
+ return op.value;
+}
+
+int pcifront_disable_msi(struct pcifront_dev *dev,
+ unsigned int dom,
+ unsigned int bus, unsigned int slot, unsigned int fun)
+{
+ struct xen_pci_op op;
+
+ if (!dev)
+ dev = pcidev;
+ if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
+ return XEN_PCI_ERR_dev_not_found;
+ memset(&op, 0, sizeof(op));
+
+ op.cmd = XEN_PCI_OP_disable_msi;
+ op.domain = dom;
+ op.bus = bus;
+ op.devfn = PCI_DEVFN(slot, fun);
+
+ pcifront_op(dev, &op);
+
+ return op.err;
+}
+
+int pcifront_enable_msix(struct pcifront_dev *dev,
+ unsigned int dom,
+ unsigned int bus, unsigned int slot, unsigned int fun,
+ struct xen_msix_entry *entries, int n)
+{
+ struct xen_pci_op op;
+
+ if (!dev)
+ dev = pcidev;
+ if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
+ return XEN_PCI_ERR_dev_not_found;
+ if (n > SH_INFO_MAX_VEC)
+ return XEN_PCI_ERR_op_failed;
+
+ memset(&op, 0, sizeof(op));
+
+ op.cmd = XEN_PCI_OP_enable_msix;
+ op.domain = dom;
+ op.bus = bus;
+ op.devfn = PCI_DEVFN(slot, fun);
+ op.value = n;
+
+ memcpy(op.msix_entries, entries, n * sizeof(*entries));
+
+ pcifront_op(dev, &op);
+
+ if (op.err)
+ return op.err;
+
+ memcpy(entries, op.msix_entries, n * sizeof(*entries));
+
+ return 0;
+}
+
+
+int pcifront_disable_msix(struct pcifront_dev *dev,
+ unsigned int dom,
+ unsigned int bus, unsigned int slot, unsigned int fun)
+{
+ struct xen_pci_op op;
+
+ if (!dev)
+ dev = pcidev;
+ if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
+ return XEN_PCI_ERR_dev_not_found;
+ memset(&op, 0, sizeof(op));
+
+ op.cmd = XEN_PCI_OP_disable_msix;
+ op.domain = dom;
+ op.bus = bus;
+ op.devfn = PCI_DEVFN(slot, fun);
+
+ pcifront_op(dev, &op);
+
+ return op.err;
+}
--- /dev/null
+/*
+ ****************************************************************************
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: sched.c
+ * Author: Grzegorz Milos
+ * Changes: Robert Kaiser
+ *
+ * Date: Aug 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: simple scheduler for Mini-Os
+ *
+ * The scheduler is non-preemptive (cooperative), and schedules according
+ * to Round Robin algorithm.
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <mini-os/os.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/time.h>
+#include <mini-os/mm.h>
+#include <mini-os/types.h>
+#include <mini-os/lib.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/list.h>
+#include <mini-os/sched.h>
+#include <mini-os/semaphore.h>
+
+
+#ifdef SCHED_DEBUG
+#define DEBUG(_f, _a...) \
+ printk("MINI_OS(file=sched.c, line=%d) " _f "\n", __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...) ((void)0)
+#endif
+
+MINIOS_TAILQ_HEAD(thread_list, struct thread);
+
+struct thread *idle_thread = NULL;
+static struct thread_list exited_threads = MINIOS_TAILQ_HEAD_INITIALIZER(exited_threads);
+static struct thread_list thread_list = MINIOS_TAILQ_HEAD_INITIALIZER(thread_list);
+static int threads_started;
+
+struct thread *main_thread;
+
+void inline print_runqueue(void)
+{
+ struct thread *th;
+ MINIOS_TAILQ_FOREACH(th, &thread_list, thread_list)
+ {
+ printk(" Thread \"%s\", runnable=%d\n", th->name, is_runnable(th));
+ }
+ printk("\n");
+}
+
+void schedule(void)
+{
+ struct thread *prev, *next, *thread, *tmp;
+ unsigned long flags;
+
+ if (irqs_disabled()) {
+ printk("Must not call schedule() with IRQs disabled\n");
+ BUG();
+ }
+
+ prev = current;
+ local_irq_save(flags);
+
+ if (in_callback) {
+ printk("Must not call schedule() from a callback\n");
+ BUG();
+ }
+
+ do {
+ /* Examine all threads.
+ Find a runnable thread, but also wake up expired ones and find the
+ time when the next timeout expires, else use 10 seconds. */
+ s_time_t now = NOW();
+ s_time_t min_wakeup_time = now + SECONDS(10);
+ next = NULL;
+ MINIOS_TAILQ_FOREACH_SAFE(thread, &thread_list, thread_list, tmp)
+ {
+ if (!is_runnable(thread) && thread->wakeup_time != 0LL)
+ {
+ if (thread->wakeup_time <= now)
+ wake(thread);
+ else if (thread->wakeup_time < min_wakeup_time)
+ min_wakeup_time = thread->wakeup_time;
+ }
+ if(is_runnable(thread))
+ {
+ next = thread;
+ /* Put this thread on the end of the list */
+ MINIOS_TAILQ_REMOVE(&thread_list, thread, thread_list);
+ MINIOS_TAILQ_INSERT_TAIL(&thread_list, thread, thread_list);
+ break;
+ }
+ }
+ if (next)
+ break;
+ /* block until the next timeout expires, or for 10 secs, whichever comes first */
+ block_domain(min_wakeup_time);
+ /* handle pending events if any */
+ force_evtchn_callback();
+ } while(1);
+ local_irq_restore(flags);
+ /* Interrupting the switch is equivalent to having the next thread
+ inturrupted at the return instruction. And therefore at safe point. */
+ if(prev != next) switch_threads(prev, next);
+
+ MINIOS_TAILQ_FOREACH_SAFE(thread, &exited_threads, thread_list, tmp)
+ {
+ if(thread != prev)
+ {
+ MINIOS_TAILQ_REMOVE(&exited_threads, thread, thread_list);
+ free_pages(thread->stack, STACK_SIZE_PAGE_ORDER);
+ xfree(thread);
+ }
+ }
+}
+
+struct thread* create_thread(char *name, void (*function)(void *), void *data)
+{
+ struct thread *thread;
+ unsigned long flags;
+ /* Call architecture specific setup. */
+ thread = arch_create_thread(name, function, data);
+ /* Not runable, not exited, not sleeping */
+ thread->flags = 0;
+ thread->wakeup_time = 0LL;
+#ifdef HAVE_LIBC
+ _REENT_INIT_PTR((&thread->reent))
+#endif
+ set_runnable(thread);
+ local_irq_save(flags);
+ MINIOS_TAILQ_INSERT_TAIL(&thread_list, thread, thread_list);
+ local_irq_restore(flags);
+ return thread;
+}
+
+#ifdef HAVE_LIBC
+static struct _reent callback_reent;
+struct _reent *__getreent(void)
+{
+ struct _reent *_reent;
+
+ if (!threads_started)
+ _reent = _impure_ptr;
+ else if (in_callback)
+ _reent = &callback_reent;
+ else
+ _reent = &get_current()->reent;
+
+#ifndef NDEBUG
+#if defined(__x86_64__) || defined(__x86__)
+ {
+#ifdef __x86_64__
+ register unsigned long sp asm ("rsp");
+#else
+ register unsigned long sp asm ("esp");
+#endif
+ if ((sp & (STACK_SIZE-1)) < STACK_SIZE / 16) {
+ static int overflowing;
+ if (!overflowing) {
+ overflowing = 1;
+ printk("stack overflow\n");
+ BUG();
+ }
+ }
+ }
+#endif
+#else
+#error Not implemented yet
+#endif
+ return _reent;
+}
+#endif
+
+void exit_thread(void)
+{
+ unsigned long flags;
+ struct thread *thread = current;
+ printk("Thread \"%s\" exited.\n", thread->name);
+ local_irq_save(flags);
+ /* Remove from the thread list */
+ MINIOS_TAILQ_REMOVE(&thread_list, thread, thread_list);
+ clear_runnable(thread);
+ /* Put onto exited list */
+ MINIOS_TAILQ_INSERT_HEAD(&exited_threads, thread, thread_list);
+ local_irq_restore(flags);
+ /* Schedule will free the resources */
+ while(1)
+ {
+ schedule();
+ printk("schedule() returned! Trying again\n");
+ }
+}
+
+void block(struct thread *thread)
+{
+ thread->wakeup_time = 0LL;
+ clear_runnable(thread);
+}
+
+void msleep(uint32_t millisecs)
+{
+ struct thread *thread = get_current();
+ thread->wakeup_time = NOW() + MILLISECS(millisecs);
+ clear_runnable(thread);
+ schedule();
+}
+
+void wake(struct thread *thread)
+{
+ thread->wakeup_time = 0LL;
+ set_runnable(thread);
+}
+
+void idle_thread_fn(void *unused)
+{
+ threads_started = 1;
+ while (1) {
+ block(current);
+ schedule();
+ }
+}
+
+DECLARE_MUTEX(mutex);
+
+void th_f1(void *data)
+{
+ struct timeval tv1, tv2;
+
+ for(;;)
+ {
+ down(&mutex);
+ printk("Thread \"%s\" got semaphore, runnable %d\n", current->name, is_runnable(current));
+ schedule();
+ printk("Thread \"%s\" releases the semaphore\n", current->name);
+ up(&mutex);
+
+
+ gettimeofday(&tv1, NULL);
+ for(;;)
+ {
+ gettimeofday(&tv2, NULL);
+ if(tv2.tv_sec - tv1.tv_sec > 2) break;
+ }
+
+
+ schedule();
+ }
+}
+
+void th_f2(void *data)
+{
+ for(;;)
+ {
+ printk("Thread OTHER executing, data 0x%lx\n", data);
+ schedule();
+ }
+}
+
+
+
+void init_sched(void)
+{
+ printk("Initialising scheduler\n");
+
+#ifdef HAVE_LIBC
+ _REENT_INIT_PTR((&callback_reent))
+#endif
+ idle_thread = create_thread("Idle", idle_thread_fn, NULL);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- /dev/null
+/******************************************************************************
+ * test.c
+ *
+ * Test code for all the various frontends; split from kernel.c
+ *
+ * Copyright (c) 2002-2003, K A Fraser & R Neugebauer
+ * Copyright (c) 2005, Grzegorz Milos, Intel Research Cambridge
+ * Copyright (c) 2006, Robert Kaiser, FH Wiesbaden
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <mini-os/os.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/mm.h>
+#include <mini-os/events.h>
+#include <mini-os/time.h>
+#include <mini-os/types.h>
+#include <mini-os/lib.h>
+#include <mini-os/sched.h>
+#include <mini-os/xenbus.h>
+#include <mini-os/gnttab.h>
+#include <mini-os/netfront.h>
+#include <mini-os/blkfront.h>
+#include <mini-os/fbfront.h>
+#include <mini-os/pcifront.h>
+#include <mini-os/xmalloc.h>
+#include <fcntl.h>
+#include <xen/features.h>
+#include <xen/version.h>
+
+#ifdef CONFIG_XENBUS
+static unsigned int do_shutdown = 0;
+static unsigned int shutdown_reason;
+static DECLARE_WAIT_QUEUE_HEAD(shutdown_queue);
+#endif
+
+#ifdef CONFIG_XENBUS
+void test_xenbus(void);
+
+static void xenbus_tester(void *p)
+{
+ test_xenbus();
+}
+#endif
+
+#ifndef HAVE_LIBC
+/* Should be random enough for our uses */
+int rand(void)
+{
+ static unsigned int previous;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ previous += tv.tv_sec + tv.tv_usec;
+ previous *= RAND_MIX;
+ return previous;
+}
+#endif
+
+static void periodic_thread(void *p)
+{
+ struct timeval tv;
+ printk("Periodic thread started.\n");
+ for(;;)
+ {
+ gettimeofday(&tv, NULL);
+ printk("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec);
+ msleep(1000);
+ }
+}
+
+#ifdef CONFIG_NETFRONT
+static struct netfront_dev *net_dev;
+static struct semaphore net_sem = __SEMAPHORE_INITIALIZER(net_sem, 0);
+
+static void netfront_thread(void *p)
+{
+ net_dev = init_netfront(NULL, NULL, NULL, NULL);
+ up(&net_sem);
+}
+#endif
+
+#ifdef CONFIG_BLKFRONT
+static struct blkfront_dev *blk_dev;
+static struct blkfront_info blk_info;
+static uint64_t blk_size_read;
+static uint64_t blk_size_write;
+static struct semaphore blk_sem = __SEMAPHORE_INITIALIZER(blk_sem, 0);;
+
+struct blk_req {
+ struct blkfront_aiocb aiocb;
+ int rand_value;
+ struct blk_req *next;
+};
+
+#ifdef BLKTEST_WRITE
+static struct blk_req *blk_to_read;
+#endif
+
+static struct blk_req *blk_alloc_req(uint64_t sector)
+{
+ struct blk_req *req = xmalloc(struct blk_req);
+ req->aiocb.aio_dev = blk_dev;
+ req->aiocb.aio_buf = _xmalloc(blk_info.sector_size, blk_info.sector_size);
+ req->aiocb.aio_nbytes = blk_info.sector_size;
+ req->aiocb.aio_offset = sector * blk_info.sector_size;
+ req->aiocb.data = req;
+ req->next = NULL;
+ return req;
+}
+
+static void blk_read_completed(struct blkfront_aiocb *aiocb, int ret)
+{
+ struct blk_req *req = aiocb->data;
+ if (ret)
+ printk("got error code %d when reading at offset %ld\n", ret, aiocb->aio_offset);
+ else
+ blk_size_read += blk_info.sector_size;
+ free(aiocb->aio_buf);
+ free(req);
+}
+
+static void blk_read_sector(uint64_t sector)
+{
+ struct blk_req *req;
+
+ req = blk_alloc_req(sector);
+ req->aiocb.aio_cb = blk_read_completed;
+
+ blkfront_aio_read(&req->aiocb);
+}
+
+#ifdef BLKTEST_WRITE
+static void blk_write_read_completed(struct blkfront_aiocb *aiocb, int ret)
+{
+ struct blk_req *req = aiocb->data;
+ int rand_value;
+ int i;
+ int *buf;
+
+ if (ret) {
+ printk("got error code %d when reading back at offset %ld\n", ret, aiocb->aio_offset);
+ free(aiocb->aio_buf);
+ free(req);
+ return;
+ }
+ blk_size_read += blk_info.sector_size;
+ buf = (int*) aiocb->aio_buf;
+ rand_value = req->rand_value;
+ for (i = 0; i < blk_info.sector_size / sizeof(int); i++) {
+ if (buf[i] != rand_value) {
+ printk("bogus data at offset %ld\n", aiocb->aio_offset + i);
+ break;
+ }
+ rand_value *= RAND_MIX;
+ }
+ free(aiocb->aio_buf);
+ free(req);
+}
+
+static void blk_write_completed(struct blkfront_aiocb *aiocb, int ret)
+{
+ struct blk_req *req = aiocb->data;
+ if (ret) {
+ printk("got error code %d when writing at offset %ld\n", ret, aiocb->aio_offset);
+ free(aiocb->aio_buf);
+ free(req);
+ return;
+ }
+ blk_size_write += blk_info.sector_size;
+ /* Push write check */
+ req->next = blk_to_read;
+ blk_to_read = req;
+}
+
+static void blk_write_sector(uint64_t sector)
+{
+ struct blk_req *req;
+ int rand_value;
+ int i;
+ int *buf;
+
+ req = blk_alloc_req(sector);
+ req->aiocb.aio_cb = blk_write_completed;
+ req->rand_value = rand_value = rand();
+
+ buf = (int*) req->aiocb.aio_buf;
+ for (i = 0; i < blk_info.sector_size / sizeof(int); i++) {
+ buf[i] = rand_value;
+ rand_value *= RAND_MIX;
+ }
+
+ blkfront_aio_write(&req->aiocb);
+}
+#endif
+
+static void blkfront_thread(void *p)
+{
+ time_t lasttime = 0;
+
+ blk_dev = init_blkfront(NULL, &blk_info);
+ if (!blk_dev) {
+ up(&blk_sem);
+ return;
+ }
+
+ if (blk_info.info & VDISK_CDROM)
+ printk("Block device is a CDROM\n");
+ if (blk_info.info & VDISK_REMOVABLE)
+ printk("Block device is removable\n");
+ if (blk_info.info & VDISK_READONLY)
+ printk("Block device is read-only\n");
+
+#ifdef BLKTEST_WRITE
+ if (blk_info.mode == O_RDWR) {
+ blk_write_sector(0);
+ blk_write_sector(blk_info.sectors-1);
+ } else
+#endif
+ {
+ blk_read_sector(0);
+ blk_read_sector(blk_info.sectors-1);
+ }
+
+ while (!do_shutdown) {
+ uint64_t sector = rand() % blk_info.sectors;
+ struct timeval tv;
+#ifdef BLKTEST_WRITE
+ if (blk_info.mode == O_RDWR)
+ blk_write_sector(sector);
+ else
+#endif
+ blk_read_sector(sector);
+ blkfront_aio_poll(blk_dev);
+ gettimeofday(&tv, NULL);
+ if (tv.tv_sec > lasttime + 10) {
+ printk("%llu read, %llu write\n", blk_size_read, blk_size_write);
+ lasttime = tv.tv_sec;
+ }
+
+#ifdef BLKTEST_WRITE
+ while (blk_to_read) {
+ struct blk_req *req = blk_to_read;
+ blk_to_read = blk_to_read->next;
+ req->aiocb.aio_cb = blk_write_read_completed;
+ blkfront_aio_read(&req->aiocb);
+ }
+#endif
+ }
+ up(&blk_sem);
+}
+#endif
+
+#if defined(CONFIG_FBFRONT) && defined(CONFIG_KBDFRONT)
+#define WIDTH 800
+#define HEIGHT 600
+#define DEPTH 32
+
+static uint32_t *fb;
+static int refresh_period = 50;
+static struct fbfront_dev *fb_dev;
+static struct semaphore fbfront_sem = __SEMAPHORE_INITIALIZER(fbfront_sem, 0);
+
+static void fbfront_drawvert(int x, int y1, int y2, uint32_t color)
+{
+ int y;
+ if (x < 0)
+ return;
+ if (x >= WIDTH)
+ return;
+ if (y1 < 0)
+ y1 = 0;
+ if (y2 >= HEIGHT)
+ y2 = HEIGHT-1;
+ for (y = y1; y <= y2; y++)
+ fb[x + y*WIDTH] ^= color;
+}
+
+static void fbfront_drawhoriz(int x1, int x2, int y, uint32_t color)
+{
+ int x;
+ if (y < 0)
+ return;
+ if (y >= HEIGHT)
+ return;
+ if (x1 < 0)
+ x1 = 0;
+ if (x2 >= WIDTH)
+ x2 = WIDTH-1;
+ for (x = x1; x <= x2; x++)
+ fb[x + y*WIDTH] ^= color;
+}
+
+static void fbfront_thread(void *p)
+{
+ size_t line_length = WIDTH * (DEPTH / 8);
+ size_t memsize = HEIGHT * line_length;
+ unsigned long *mfns;
+ int i, n = (memsize + PAGE_SIZE-1) / PAGE_SIZE;
+
+ memsize = n * PAGE_SIZE;
+ fb = _xmalloc(memsize, PAGE_SIZE);
+ memset(fb, 0, memsize);
+ mfns = xmalloc_array(unsigned long, n);
+ for (i = 0; i < n; i++)
+ mfns[i] = virtual_to_mfn((char *) fb + i * PAGE_SIZE);
+ fb_dev = init_fbfront(NULL, mfns, WIDTH, HEIGHT, DEPTH, line_length, n);
+ xfree(mfns);
+ if (!fb_dev) {
+ xfree(fb);
+ }
+ up(&fbfront_sem);
+}
+
+static void clip_cursor(int *x, int *y)
+{
+ if (*x < 0)
+ *x = 0;
+ if (*x >= WIDTH)
+ *x = WIDTH - 1;
+ if (*y < 0)
+ *y = 0;
+ if (*y >= HEIGHT)
+ *y = HEIGHT - 1;
+}
+
+static void refresh_cursor(int new_x, int new_y)
+{
+ static int old_x = -1, old_y = -1;
+
+ if (!refresh_period)
+ return;
+
+ if (old_x != -1 && old_y != -1) {
+ fbfront_drawvert(old_x, old_y + 1, old_y + 8, 0xffffffff);
+ fbfront_drawhoriz(old_x + 1, old_x + 8, old_y, 0xffffffff);
+ fbfront_update(fb_dev, old_x, old_y, 9, 9);
+ }
+ old_x = new_x;
+ old_y = new_y;
+ fbfront_drawvert(new_x, new_y + 1, new_y + 8, 0xffffffff);
+ fbfront_drawhoriz(new_x + 1, new_x + 8, new_y, 0xffffffff);
+ fbfront_update(fb_dev, new_x, new_y, 9, 9);
+}
+
+static struct kbdfront_dev *kbd_dev;
+static struct semaphore kbd_sem = __SEMAPHORE_INITIALIZER(kbd_sem, 0);
+static void kbdfront_thread(void *p)
+{
+ DEFINE_WAIT(w);
+ DEFINE_WAIT(w2);
+ DEFINE_WAIT(w3);
+ int x = WIDTH / 2, y = HEIGHT / 2, z = 0;
+
+ kbd_dev = init_kbdfront(NULL, 1);
+ down(&fbfront_sem);
+ if (!kbd_dev) {
+ up(&kbd_sem);
+ return;
+ }
+
+ refresh_cursor(x, y);
+ while (1) {
+ union xenkbd_in_event kbdevent;
+ union xenfb_in_event fbevent;
+ int sleep = 1;
+
+ add_waiter(w, kbdfront_queue);
+ add_waiter(w2, fbfront_queue);
+ add_waiter(w3, shutdown_queue);
+
+ rmb();
+ if (do_shutdown)
+ break;
+
+ while (kbdfront_receive(kbd_dev, &kbdevent, 1) != 0) {
+ sleep = 0;
+ switch(kbdevent.type) {
+ case XENKBD_TYPE_MOTION:
+ printk("motion x:%d y:%d z:%d\n",
+ kbdevent.motion.rel_x,
+ kbdevent.motion.rel_y,
+ kbdevent.motion.rel_z);
+ x += kbdevent.motion.rel_x;
+ y += kbdevent.motion.rel_y;
+ z += kbdevent.motion.rel_z;
+ clip_cursor(&x, &y);
+ refresh_cursor(x, y);
+ break;
+ case XENKBD_TYPE_POS:
+ printk("pos x:%d y:%d dz:%d\n",
+ kbdevent.pos.abs_x,
+ kbdevent.pos.abs_y,
+ kbdevent.pos.rel_z);
+ x = kbdevent.pos.abs_x;
+ y = kbdevent.pos.abs_y;
+ z = kbdevent.pos.rel_z;
+ clip_cursor(&x, &y);
+ refresh_cursor(x, y);
+ break;
+ case XENKBD_TYPE_KEY:
+ printk("key %d %s\n",
+ kbdevent.key.keycode,
+ kbdevent.key.pressed ? "pressed" : "released");
+ if (kbdevent.key.keycode == BTN_LEFT) {
+ printk("mouse %s at (%d,%d,%d)\n",
+ kbdevent.key.pressed ? "clic" : "release", x, y, z);
+ if (kbdevent.key.pressed) {
+ uint32_t color = rand();
+ fbfront_drawvert(x - 16, y - 16, y + 15, color);
+ fbfront_drawhoriz(x - 16, x + 15, y + 16, color);
+ fbfront_drawvert(x + 16, y - 15, y + 16, color);
+ fbfront_drawhoriz(x - 15, x + 16, y - 16, color);
+ fbfront_update(fb_dev, x - 16, y - 16, 33, 33);
+ }
+ } else if (kbdevent.key.keycode == KEY_Q) {
+ shutdown_reason = SHUTDOWN_poweroff;
+ wmb();
+ do_shutdown = 1;
+ wmb();
+ wake_up(&shutdown_queue);
+ }
+ break;
+ }
+ }
+ while (fbfront_receive(fb_dev, &fbevent, 1) != 0) {
+ sleep = 0;
+ switch(fbevent.type) {
+ case XENFB_TYPE_REFRESH_PERIOD:
+ refresh_period = fbevent.refresh_period.period;
+ printk("refresh period %d\n", refresh_period);
+ refresh_cursor(x, y);
+ break;
+ }
+ }
+ if (sleep)
+ schedule();
+ remove_waiter(w3, shutdown_queue);
+ remove_waiter(w2, fbfront_queue);
+ remove_waiter(w, kbdfront_queue);
+ }
+ up(&kbd_sem);
+}
+#endif
+
+#ifdef CONFIG_PCIFRONT
+static struct pcifront_dev *pci_dev;
+static struct semaphore pci_sem = __SEMAPHORE_INITIALIZER(pci_sem, 0);
+
+static void print_pcidev(unsigned int domain, unsigned int bus, unsigned int slot, unsigned int fun)
+{
+ unsigned int vendor, device, rev, class;
+
+ pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x00, 2, &vendor);
+ pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x02, 2, &device);
+ pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x08, 1, &rev);
+ pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x0a, 2, &class);
+
+ printk("%04x:%02x:%02x.%02x %04x: %04x:%04x (rev %02x)\n", domain, bus, slot, fun, class, vendor, device, rev);
+}
+
+static void pcifront_thread(void *p)
+{
+ pcifront_watches(NULL);
+ pci_dev = init_pcifront(NULL);
+ if (!pci_dev) {
+ up(&pci_sem);
+ return;
+ }
+ printk("PCI devices:\n");
+ pcifront_scan(pci_dev, print_pcidev);
+ up(&pci_sem);
+}
+#endif
+
+void shutdown_frontends(void)
+{
+#ifdef CONFIG_NETFRONT
+ down(&net_sem);
+ if (net_dev)
+ shutdown_netfront(net_dev);
+#endif
+
+#ifdef CONFIG_BLKFRONT
+ down(&blk_sem);
+ if (blk_dev)
+ shutdown_blkfront(blk_dev);
+#endif
+
+#if defined(CONFIG_FBFRONT) && defined(CONFIG_KBDFRONT)
+ if (fb_dev)
+ shutdown_fbfront(fb_dev);
+
+ down(&kbd_sem);
+ if (kbd_dev)
+ shutdown_kbdfront(kbd_dev);
+#endif
+
+#ifdef CONFIG_PCIFRONT
+ down(&pci_sem);
+ if (pci_dev)
+ shutdown_pcifront(pci_dev);
+#endif
+}
+
+#ifdef CONFIG_XENBUS
+void app_shutdown(unsigned reason)
+{
+ shutdown_reason = reason;
+ wmb();
+ do_shutdown = 1;
+ wmb();
+ wake_up(&shutdown_queue);
+}
+
+static void shutdown_thread(void *p)
+{
+ DEFINE_WAIT(w);
+
+ while (1) {
+ add_waiter(w, shutdown_queue);
+ rmb();
+ if (do_shutdown) {
+ rmb();
+ break;
+ }
+ schedule();
+ remove_waiter(w, shutdown_queue);
+ }
+
+ shutdown_frontends();
+
+ HYPERVISOR_shutdown(shutdown_reason);
+}
+#endif
+
+int app_main(start_info_t *si)
+{
+ printk("Test main: start_info=%p\n", si);
+#ifdef CONFIG_XENBUS
+ create_thread("xenbus_tester", xenbus_tester, si);
+#endif
+ create_thread("periodic_thread", periodic_thread, si);
+#ifdef CONFIG_NETFRONT
+ create_thread("netfront", netfront_thread, si);
+#endif
+#ifdef CONFIG_BLKFRONT
+ create_thread("blkfront", blkfront_thread, si);
+#endif
+#if defined(CONFIG_FBFRONT) && defined(CONFIG_KBDFRONT)
+ create_thread("fbfront", fbfront_thread, si);
+ create_thread("kbdfront", kbdfront_thread, si);
+#endif
+#ifdef CONFIG_PCIFRONT
+ create_thread("pcifront", pcifront_thread, si);
+#endif
+#ifdef CONFIG_XENBUS
+ create_thread("shutdown", shutdown_thread, si);
+#endif
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense. All rights reserved.
+ *
+ * This code has been derived from drivers/char/tpm.c
+ * from the linux kernel
+ *
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * This code has also been derived from drivers/char/tpm/tpm_tis.c
+ * from the linux kernel
+ *
+ * Copyright (C) 2005, 2006 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, version 2
+ * of the License
+ */
+#include <mini-os/ioremap.h>
+#include <mini-os/iorw.h>
+#include <mini-os/tpm_tis.h>
+#include <mini-os/os.h>
+#include <mini-os/sched.h>
+#include <mini-os/byteorder.h>
+#include <mini-os/events.h>
+#include <mini-os/wait.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/lib.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#ifndef min
+ #define min( a, b ) ( ((a) < (b)) ? (a) : (b) )
+#endif
+#define ADJUST_TIMEOUTS_TO_STANDARD(initial,standard,timeout_no) \
+ if((initial) < (standard)){ \
+ (initial) = (standard); \
+ printk("Timeout %c was adjusted to standard value.\n",timeout_no); \
+ }
+
+#define TPM_HEADER_SIZE 10
+
+#define TPM_BUFSIZE 2048
+
+struct tpm_input_header {
+ uint16_t tag;
+ uint32_t length;
+ uint32_t ordinal;
+}__attribute__((packed));
+
+struct tpm_output_header {
+ uint16_t tag;
+ uint32_t length;
+ uint32_t return_code;
+}__attribute__((packed));
+
+struct stclear_flags_t {
+ uint16_t tag;
+ uint8_t deactivated;
+ uint8_t disableForceClear;
+ uint8_t physicalPresence;
+ uint8_t physicalPresenceLock;
+ uint8_t bGlobalLock;
+}__attribute__((packed));
+
+struct tpm_version_t {
+ uint8_t Major;
+ uint8_t Minor;
+ uint8_t revMajor;
+ uint8_t revMinor;
+}__attribute__((packed));
+
+struct tpm_version_1_2_t {
+ uint16_t tag;
+ uint8_t Major;
+ uint8_t Minor;
+ uint8_t revMajor;
+ uint8_t revMinor;
+}__attribute__((packed));
+
+struct timeout_t {
+ uint32_t a;
+ uint32_t b;
+ uint32_t c;
+ uint32_t d;
+}__attribute__((packed));
+
+struct duration_t {
+ uint32_t tpm_short;
+ uint32_t tpm_medium;
+ uint32_t tpm_long;
+}__attribute__((packed));
+
+struct permanent_flags_t {
+ uint16_t tag;
+ uint8_t disable;
+ uint8_t ownership;
+ uint8_t deactivated;
+ uint8_t readPubek;
+ uint8_t disableOwnerClear;
+ uint8_t allowMaintenance;
+ uint8_t physicalPresenceLifetimeLock;
+ uint8_t physicalPresenceHWEnable;
+ uint8_t physicalPresenceCMDEnable;
+ uint8_t CEKPUsed;
+ uint8_t TPMpost;
+ uint8_t TPMpostLock;
+ uint8_t FIPS;
+ uint8_t operator;
+ uint8_t enableRevokeEK;
+ uint8_t nvLocked;
+ uint8_t readSRKPub;
+ uint8_t tpmEstablished;
+ uint8_t maintenanceDone;
+ uint8_t disableFullDALogicInfo;
+}__attribute__((packed));
+
+typedef union {
+ struct permanent_flags_t perm_flags;
+ struct stclear_flags_t stclear_flags;
+ bool owned;
+ uint32_t num_pcrs;
+ struct tpm_version_t tpm_version;
+ struct tpm_version_1_2_t tpm_version_1_2;
+ uint32_t manufacturer_id;
+ struct timeout_t timeout;
+ struct duration_t duration;
+} cap_t;
+
+struct tpm_getcap_params_in {
+ uint32_t cap;
+ uint32_t subcap_size;
+ uint32_t subcap;
+}__attribute__((packed));
+
+struct tpm_getcap_params_out {
+ uint32_t cap_size;
+ cap_t cap;
+}__attribute__((packed));
+
+struct tpm_readpubek_params_out {
+ uint8_t algorithm[4];
+ uint8_t encscheme[2];
+ uint8_t sigscheme[2];
+ uint32_t paramsize;
+ uint8_t parameters[12]; /*assuming RSA*/
+ uint32_t keysize;
+ uint8_t modulus[256];
+ uint8_t checksum[20];
+}__attribute__((packed));
+
+typedef union {
+ struct tpm_input_header in;
+ struct tpm_output_header out;
+} tpm_cmd_header;
+
+#define TPM_DIGEST_SIZE 20
+struct tpm_pcrread_out {
+ uint8_t pcr_result[TPM_DIGEST_SIZE];
+}__attribute__((packed));
+
+struct tpm_pcrread_in {
+ uint32_t pcr_idx;
+}__attribute__((packed));
+
+struct tpm_pcrextend_in {
+ uint32_t pcr_idx;
+ uint8_t hash[TPM_DIGEST_SIZE];
+}__attribute__((packed));
+
+typedef union {
+ struct tpm_getcap_params_out getcap_out;
+ struct tpm_readpubek_params_out readpubek_out;
+ uint8_t readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)];
+ struct tpm_getcap_params_in getcap_in;
+ struct tpm_pcrread_in pcrread_in;
+ struct tpm_pcrread_out pcrread_out;
+ struct tpm_pcrextend_in pcrextend_in;
+} tpm_cmd_params;
+
+struct tpm_cmd_t {
+ tpm_cmd_header header;
+ tpm_cmd_params params;
+}__attribute__((packed));
+
+
+enum tpm_duration {
+ TPM_SHORT = 0,
+ TPM_MEDIUM = 1,
+ TPM_LONG = 2,
+ TPM_UNDEFINED,
+};
+
+#define TPM_MAX_ORDINAL 243
+#define TPM_MAX_PROTECTED_ORDINAL 12
+#define TPM_PROTECTED_ORDINAL_MASK 0xFF
+
+extern const uint8_t tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL];
+extern const uint8_t tpm_ordinal_duration[TPM_MAX_ORDINAL];
+
+#define TPM_DIGEST_SIZE 20
+#define TPM_ERROR_SIZE 10
+#define TPM_RET_CODE_IDX 6
+
+/* tpm_capabilities */
+#define TPM_CAP_FLAG cpu_to_be32(4)
+#define TPM_CAP_PROP cpu_to_be32(5)
+#define CAP_VERSION_1_1 cpu_to_be32(0x06)
+#define CAP_VERSION_1_2 cpu_to_be32(0x1A)
+
+/* tpm_sub_capabilities */
+#define TPM_CAP_PROP_PCR cpu_to_be32(0x101)
+#define TPM_CAP_PROP_MANUFACTURER cpu_to_be32(0x103)
+#define TPM_CAP_FLAG_PERM cpu_to_be32(0x108)
+#define TPM_CAP_FLAG_VOL cpu_to_be32(0x109)
+#define TPM_CAP_PROP_OWNER cpu_to_be32(0x111)
+#define TPM_CAP_PROP_TIS_TIMEOUT cpu_to_be32(0x115)
+#define TPM_CAP_PROP_TIS_DURATION cpu_to_be32(0x120)
+
+
+#define TPM_INTERNAL_RESULT_SIZE 200
+#define TPM_TAG_RQU_COMMAND cpu_to_be16(193)
+#define TPM_ORD_GET_CAP cpu_to_be32(101)
+
+extern const struct tpm_input_header tpm_getcap_header;
+
+
+
+const uint8_t tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
+ TPM_UNDEFINED, /* 0 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 5 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 10 */
+ TPM_SHORT,
+};
+
+const uint8_t tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
+ TPM_UNDEFINED, /* 0 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 5 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 10 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_LONG,
+ TPM_MEDIUM, /* 15 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_SHORT, /* 20 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT, /* 25 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 30 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 35 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 40 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 45 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_LONG,
+ TPM_MEDIUM, /* 50 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 55 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 60 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 65 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 70 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 75 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 80 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 85 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 90 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 95 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 100 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 105 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 110 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 115 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 120 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 125 */
+ TPM_SHORT,
+ TPM_LONG,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 130 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_UNDEFINED, /* 135 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 140 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 145 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 150 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 155 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 160 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 165 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 170 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 175 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 180 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM, /* 185 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 190 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 195 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 200 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 205 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 210 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_UNDEFINED, /* 215 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 220 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 225 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 230 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 235 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 240 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+};
+
+const struct tpm_input_header tpm_getcap_header = {
+ .tag = TPM_TAG_RQU_COMMAND,
+ .length = cpu_to_be32(22),
+ .ordinal = TPM_ORD_GET_CAP
+};
+
+
+enum tis_access {
+ TPM_ACCESS_VALID = 0x80,
+ TPM_ACCESS_ACTIVE_LOCALITY = 0x20, /* (R) */
+ TPM_ACCESS_RELINQUISH_LOCALITY = 0x20,/* (W) */
+ TPM_ACCESS_REQUEST_PENDING = 0x04, /* (W) */
+ TPM_ACCESS_REQUEST_USE = 0x02, /* (W) */
+};
+
+enum tis_status {
+ TPM_STS_VALID = 0x80, /* (R) */
+ TPM_STS_COMMAND_READY = 0x40, /* (R) */
+ TPM_STS_DATA_AVAIL = 0x10, /* (R) */
+ TPM_STS_DATA_EXPECT = 0x08, /* (R) */
+ TPM_STS_GO = 0x20, /* (W) */
+};
+
+enum tis_int_flags {
+ TPM_GLOBAL_INT_ENABLE = 0x80000000,
+ TPM_INTF_BURST_COUNT_STATIC = 0x100,
+ TPM_INTF_CMD_READY_INT = 0x080,
+ TPM_INTF_INT_EDGE_FALLING = 0x040,
+ TPM_INTF_INT_EDGE_RISING = 0x020,
+ TPM_INTF_INT_LEVEL_LOW = 0x010,
+ TPM_INTF_INT_LEVEL_HIGH = 0x008,
+ TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
+ TPM_INTF_STS_VALID_INT = 0x002,
+ TPM_INTF_DATA_AVAIL_INT = 0x001,
+};
+
+enum tis_defaults {
+ TIS_MEM_BASE = 0xFED40000,
+ TIS_MEM_LEN = 0x5000,
+ TIS_SHORT_TIMEOUT = 750, /*ms*/
+ TIS_LONG_TIMEOUT = 2000, /*2 sec */
+};
+
+#define TPM_TIMEOUT 5
+
+#define TPM_ACCESS(t, l) (((uint8_t*)t->pages[l]) + 0x0000)
+#define TPM_INT_ENABLE(t, l) ((uint32_t*)(((uint8_t*)t->pages[l]) + 0x0008))
+#define TPM_INT_VECTOR(t, l) (((uint8_t*)t->pages[l]) + 0x000C)
+#define TPM_INT_STATUS(t, l) (((uint8_t*)t->pages[l]) + 0x0010)
+#define TPM_INTF_CAPS(t, l) ((uint32_t*)(((uint8_t*)t->pages[l]) + 0x0014))
+#define TPM_STS(t, l) ((uint8_t*)(((uint8_t*)t->pages[l]) + 0x0018))
+#define TPM_DATA_FIFO(t, l) (((uint8_t*)t->pages[l]) + 0x0024)
+
+#define TPM_DID_VID(t, l) ((uint32_t*)(((uint8_t*)t->pages[l]) + 0x0F00))
+#define TPM_RID(t, l) (((uint8_t*)t->pages[l]) + 0x0F04)
+
+struct tpm_chip {
+ int enabled_localities;
+ int locality;
+ unsigned long baseaddr;
+ uint8_t* pages[5];
+ int did, vid, rid;
+
+ uint8_t data_buffer[TPM_BUFSIZE];
+ int data_len;
+
+ s_time_t timeout_a, timeout_b, timeout_c, timeout_d;
+ s_time_t duration[3];
+
+#ifdef HAVE_LIBC
+ int fd;
+#endif
+
+ unsigned int irq;
+ struct wait_queue_head read_queue;
+ struct wait_queue_head int_queue;
+};
+
+
+static void __init_tpm_chip(struct tpm_chip* tpm) {
+ tpm->enabled_localities = TPM_TIS_EN_LOCLALL;
+ tpm->locality = -1;
+ tpm->baseaddr = 0;
+ tpm->pages[0] = tpm->pages[1] = tpm->pages[2] = tpm->pages[3] = tpm->pages[4] = NULL;
+ tpm->vid = 0;
+ tpm->did = 0;
+ tpm->irq = 0;
+ init_waitqueue_head(&tpm->read_queue);
+ init_waitqueue_head(&tpm->int_queue);
+
+ tpm->data_len = -1;
+
+#ifdef HAVE_LIBC
+ tpm->fd = -1;
+#endif
+}
+
+/*
+ * Returns max number of nsecs to wait
+ */
+s_time_t tpm_calc_ordinal_duration(struct tpm_chip *chip,
+ uint32_t ordinal)
+{
+ int duration_idx = TPM_UNDEFINED;
+ s_time_t duration = 0;
+
+ if (ordinal < TPM_MAX_ORDINAL)
+ duration_idx = tpm_ordinal_duration[ordinal];
+ else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
+ TPM_MAX_PROTECTED_ORDINAL)
+ duration_idx =
+ tpm_protected_ordinal_duration[ordinal &
+ TPM_PROTECTED_ORDINAL_MASK];
+
+ if (duration_idx != TPM_UNDEFINED) {
+ duration = chip->duration[duration_idx];
+ }
+
+ if (duration <= 0) {
+ return SECONDS(120);
+ }
+ else
+ {
+ return duration;
+ }
+}
+
+
+static int locality_enabled(struct tpm_chip* tpm, int l) {
+ return l >= 0 && tpm->enabled_localities & (1 << l);
+}
+
+static int check_locality(struct tpm_chip* tpm, int l) {
+ if(locality_enabled(tpm, l) && (ioread8(TPM_ACCESS(tpm, l)) &
+ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
+ return l;
+ }
+ return -1;
+}
+
+void release_locality(struct tpm_chip* tpm, int l, int force)
+{
+ if (locality_enabled(tpm, l) && (force || (ioread8(TPM_ACCESS(tpm, l)) &
+ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
+ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))) {
+ iowrite8(TPM_ACCESS(tpm, l), TPM_ACCESS_RELINQUISH_LOCALITY);
+ }
+}
+
+int tpm_tis_request_locality(struct tpm_chip* tpm, int l) {
+
+ s_time_t stop;
+ /*Make sure locality is valid */
+ if(!locality_enabled(tpm, l)) {
+ printk("tpm_tis_change_locality() Tried to change to locality %d, but it is disabled or invalid!\n", l);
+ return -1;
+ }
+ /* Check if we already have the current locality */
+ if(check_locality(tpm, l) >= 0) {
+ return tpm->locality = l;
+ }
+ /* Set the new locality*/
+ iowrite8(TPM_ACCESS(tpm, l), TPM_ACCESS_REQUEST_USE);
+
+ if(tpm->irq) {
+ /* Wait for interrupt */
+ wait_event_deadline(tpm->int_queue, (check_locality(tpm, l) >= 0), NOW() + tpm->timeout_a);
+
+ /* FIXME: Handle timeout event, should return error in that case */
+ return l;
+ } else {
+ /* Wait for burstcount */
+ stop = NOW() + tpm->timeout_a;
+ do {
+ if(check_locality(tpm, l) >= 0) {
+ return tpm->locality = l;
+ }
+ msleep(TPM_TIMEOUT);
+ } while(NOW() < stop);
+ }
+
+ printk("REQ LOCALITY FAILURE\n");
+ return -1;
+}
+
+static uint8_t tpm_tis_status(struct tpm_chip* tpm) {
+ return ioread8(TPM_STS(tpm, tpm->locality));
+}
+
+/* This causes the current command to be aborted */
+static void tpm_tis_ready(struct tpm_chip* tpm) {
+ iowrite8(TPM_STS(tpm, tpm->locality), TPM_STS_COMMAND_READY);
+}
+#define tpm_tis_cancel_cmd(v) tpm_tis_ready(v)
+
+static int get_burstcount(struct tpm_chip* tpm) {
+ s_time_t stop;
+ int burstcnt;
+
+ stop = NOW() + tpm->timeout_d;
+ do {
+ burstcnt = ioread8((TPM_STS(tpm, tpm->locality) + 1));
+ burstcnt += ioread8(TPM_STS(tpm, tpm->locality) + 2) << 8;
+
+ if (burstcnt) {
+ return burstcnt;
+ }
+ msleep(TPM_TIMEOUT);
+ } while(NOW() < stop);
+ return -EBUSY;
+}
+
+static int wait_for_stat(struct tpm_chip* tpm, uint8_t mask,
+ unsigned long timeout, struct wait_queue_head* queue) {
+ s_time_t stop;
+ uint8_t status;
+
+ status = tpm_tis_status(tpm);
+ if((status & mask) == mask) {
+ return 0;
+ }
+
+ if(tpm->irq) {
+ wait_event_deadline(*queue, ((tpm_tis_status(tpm) & mask) == mask), timeout);
+ /* FIXME: Check for timeout and return -ETIME */
+ return 0;
+ } else {
+ stop = NOW() + timeout;
+ do {
+ msleep(TPM_TIMEOUT);
+ status = tpm_tis_status(tpm);
+ if((status & mask) == mask)
+ return 0;
+ } while( NOW() < stop);
+ }
+ return -ETIME;
+}
+
+static int recv_data(struct tpm_chip* tpm, uint8_t* buf, size_t count) {
+ int size = 0;
+ int burstcnt;
+ while( size < count &&
+ wait_for_stat(tpm,
+ TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ tpm->timeout_c,
+ &tpm->read_queue)
+ == 0) {
+ burstcnt = get_burstcount(tpm);
+ for(; burstcnt > 0 && size < count; --burstcnt)
+ {
+ buf[size++] = ioread8(TPM_DATA_FIFO(tpm, tpm->locality));
+ }
+ }
+ return size;
+}
+
+int tpm_tis_recv(struct tpm_chip* tpm, uint8_t* buf, size_t count) {
+ int size = 0;
+ int expected, status;
+
+ if (count < TPM_HEADER_SIZE) {
+ size = -EIO;
+ goto out;
+ }
+
+ /* read first 10 bytes, including tag, paramsize, and result */
+ if((size =
+ recv_data(tpm, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) {
+ printk("Error reading tpm cmd header\n");
+ goto out;
+ }
+
+ expected = be32_to_cpu(*((uint32_t*)(buf + 2)));
+ if(expected > count) {
+ size = -EIO;
+ goto out;
+ }
+
+ if((size += recv_data(tpm, & buf[TPM_HEADER_SIZE],
+ expected - TPM_HEADER_SIZE)) < expected) {
+ printk("Unable to read rest of tpm command size=%d expected=%d\n", size, expected);
+ size = -ETIME;
+ goto out;
+ }
+
+ wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c, &tpm->int_queue);
+ status = tpm_tis_status(tpm);
+ if(status & TPM_STS_DATA_AVAIL) {
+ printk("Error: left over data\n");
+ size = -EIO;
+ goto out;
+ }
+
+out:
+ tpm_tis_ready(tpm);
+ release_locality(tpm, tpm->locality, 0);
+ return size;
+}
+int tpm_tis_send(struct tpm_chip* tpm, uint8_t* buf, size_t len) {
+ int rc;
+ int status, burstcnt = 0;
+ int count = 0;
+ uint32_t ordinal;
+
+ if(tpm_tis_request_locality(tpm, tpm->locality) < 0) {
+ return -EBUSY;
+ }
+
+ status = tpm_tis_status(tpm);
+ if((status & TPM_STS_COMMAND_READY) == 0) {
+ tpm_tis_ready(tpm);
+ if(wait_for_stat(tpm, TPM_STS_COMMAND_READY, tpm->timeout_b, &tpm->int_queue) < 0) {
+ rc = -ETIME;
+ goto out_err;
+ }
+ }
+
+ while(count < len - 1) {
+ burstcnt = get_burstcount(tpm);
+ for(;burstcnt > 0 && count < len -1; --burstcnt) {
+ iowrite8(TPM_DATA_FIFO(tpm, tpm->locality), buf[count++]);
+ }
+
+ wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c, &tpm->int_queue);
+ status = tpm_tis_status(tpm);
+ if((status & TPM_STS_DATA_EXPECT) == 0) {
+ rc = -EIO;
+ goto out_err;
+ }
+ }
+
+ /*Write last byte*/
+ iowrite8(TPM_DATA_FIFO(tpm, tpm->locality), buf[count]);
+ wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c, &tpm->read_queue);
+ status = tpm_tis_status(tpm);
+ if((status & TPM_STS_DATA_EXPECT) != 0) {
+ rc = -EIO;
+ goto out_err;
+ }
+
+ /*go and do it*/
+ iowrite8(TPM_STS(tpm, tpm->locality), TPM_STS_GO);
+
+ if(tpm->irq) {
+ /*Wait for interrupt */
+ ordinal = be32_to_cpu(*(buf + 6));
+ if(wait_for_stat(tpm,
+ TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ tpm_calc_ordinal_duration(tpm, ordinal),
+ &tpm->read_queue) < 0) {
+ rc = -ETIME;
+ goto out_err;
+ }
+ }
+#ifdef HAVE_LIBC
+ if(tpm->fd >= 0) {
+ files[tpm->fd].read = 0;
+ files[tpm->fd].tpm_tis.respgot = 0;
+ files[tpm->fd].tpm_tis.offset = 0;
+ }
+#endif
+ return len;
+
+out_err:
+ tpm_tis_ready(tpm);
+ release_locality(tpm, tpm->locality, 0);
+ return rc;
+}
+
+static void tpm_tis_irq_handler(evtchn_port_t port, struct pt_regs *regs, void* data)
+{
+ struct tpm_chip* tpm = data;
+ uint32_t interrupt;
+ int i;
+
+ interrupt = ioread32(TPM_INT_STATUS(tpm, tpm->locality));
+ if(interrupt == 0) {
+ return;
+ }
+
+ if(interrupt & TPM_INTF_DATA_AVAIL_INT) {
+ wake_up(&tpm->read_queue);
+ }
+ if(interrupt & TPM_INTF_LOCALITY_CHANGE_INT) {
+ for(i = 0; i < 5; ++i) {
+ if(check_locality(tpm, i) >= 0) {
+ break;
+ }
+ }
+ }
+ if(interrupt & (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
+ TPM_INTF_CMD_READY_INT)) {
+ wake_up(&tpm->int_queue);
+ }
+
+ /* Clear interrupts handled with TPM_EOI */
+ iowrite32(TPM_INT_STATUS(tpm, tpm->locality), interrupt);
+ ioread32(TPM_INT_STATUS(tpm, tpm->locality));
+ return;
+}
+
+/*
+ * Internal kernel interface to transmit TPM commands
+ */
+static ssize_t tpm_transmit(struct tpm_chip *chip, const uint8_t *buf,
+ size_t bufsiz)
+{
+ ssize_t rc;
+ uint32_t count, ordinal;
+ s_time_t stop;
+
+ count = be32_to_cpu(*((uint32_t *) (buf + 2)));
+ ordinal = be32_to_cpu(*((uint32_t *) (buf + 6)));
+ if (count == 0)
+ return -ENODATA;
+ if (count > bufsiz) {
+ printk("Error: invalid count value %x %zx \n", count, bufsiz);
+ return -E2BIG;
+ }
+
+ //down(&chip->tpm_mutex);
+
+ if ((rc = tpm_tis_send(chip, (uint8_t *) buf, count)) < 0) {
+ printk("tpm_transmit: tpm_send: error %ld\n", rc);
+ goto out;
+ }
+
+ if (chip->irq)
+ goto out_recv;
+
+ stop = NOW() + tpm_calc_ordinal_duration(chip, ordinal);
+ do {
+ uint8_t status = tpm_tis_status(chip);
+ if ((status & (TPM_STS_DATA_AVAIL | TPM_STS_VALID)) ==
+ (TPM_STS_DATA_AVAIL | TPM_STS_VALID))
+ goto out_recv;
+
+ if ((status == TPM_STS_COMMAND_READY)) {
+ printk("TPM Error: Operation Canceled\n");
+ rc = -ECANCELED;
+ goto out;
+ }
+
+ msleep(TPM_TIMEOUT); /* CHECK */
+ rmb();
+ } while (NOW() < stop);
+
+ /* Cancel the command */
+ tpm_tis_cancel_cmd(chip);
+ printk("TPM Operation Timed out\n");
+ rc = -ETIME;
+ goto out;
+
+out_recv:
+ if((rc = tpm_tis_recv(chip, (uint8_t *) buf, bufsiz)) < 0) {
+ printk("tpm_transmit: tpm_recv: error %d\n", rc);
+ }
+out:
+ //up(&chip->tpm_mutex);
+ return rc;
+}
+
+static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
+ int len, const char *desc)
+{
+ int err;
+
+ len = tpm_transmit(chip,(uint8_t *) cmd, len);
+ if (len < 0)
+ return len;
+ if (len == TPM_ERROR_SIZE) {
+ err = be32_to_cpu(cmd->header.out.return_code);
+ printk("A TPM error (%d) occurred %s\n", err, desc);
+ return err;
+ }
+ return 0;
+}
+
+int tpm_get_timeouts(struct tpm_chip *chip)
+{
+ struct tpm_cmd_t tpm_cmd;
+ struct timeout_t *timeout_cap;
+ struct duration_t *duration_cap;
+ ssize_t rc;
+ uint32_t timeout;
+ unsigned int scale = 1;
+
+ tpm_cmd.header.in = tpm_getcap_header;
+ tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
+ tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
+ tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
+
+ if((rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
+ "attempting to determine the timeouts")) != 0) {
+ printk("transmit failed %d\n", rc);
+ goto duration;
+ }
+
+ if(be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
+ be32_to_cpu(tpm_cmd.header.out.length) !=
+ sizeof(tpm_cmd.header.out) + sizeof(uint32_t) + 4 * sizeof(uint32_t)) {
+ return -EINVAL;
+ }
+
+ timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
+ /* Don't overwrite default if value is 0 */
+ timeout = be32_to_cpu(timeout_cap->a);
+ if(timeout && timeout < 1000) {
+ /* timeouts in msc rather usec */
+ scale = 1000;
+ }
+ if (timeout)
+ chip->timeout_a = MICROSECS(timeout * scale); /*Convert to msec */
+ ADJUST_TIMEOUTS_TO_STANDARD(chip->timeout_a,MILLISECS(TIS_SHORT_TIMEOUT),'a');
+
+ timeout = be32_to_cpu(timeout_cap->b);
+ if (timeout)
+ chip->timeout_b = MICROSECS(timeout * scale); /*Convert to msec */
+ ADJUST_TIMEOUTS_TO_STANDARD(chip->timeout_b,MILLISECS(TIS_LONG_TIMEOUT),'b');
+
+ timeout = be32_to_cpu(timeout_cap->c);
+ if (timeout)
+ chip->timeout_c = MICROSECS(timeout * scale); /*Convert to msec */
+ ADJUST_TIMEOUTS_TO_STANDARD(chip->timeout_c,MILLISECS(TIS_SHORT_TIMEOUT),'c');
+
+ timeout = be32_to_cpu(timeout_cap->d);
+ if (timeout)
+ chip->timeout_d = MICROSECS(timeout * scale); /*Convert to msec */
+ ADJUST_TIMEOUTS_TO_STANDARD(chip->timeout_d,MILLISECS(TIS_SHORT_TIMEOUT),'d');
+
+duration:
+ tpm_cmd.header.in = tpm_getcap_header;
+ tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
+ tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
+ tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION;
+
+ if((rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
+ "attempting to determine the durations")) < 0) {
+ return rc;
+ }
+
+ if(be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
+ be32_to_cpu(tpm_cmd.header.out.length) !=
+ sizeof(tpm_cmd.header.out) + sizeof(uint32_t) + 3 * sizeof(uint32_t)) {
+ return -EINVAL;
+ }
+
+ duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
+ chip->duration[TPM_SHORT] = MICROSECS(be32_to_cpu(duration_cap->tpm_short));
+ chip->duration[TPM_MEDIUM] = MICROSECS(be32_to_cpu(duration_cap->tpm_medium));
+ chip->duration[TPM_LONG] = MICROSECS(be32_to_cpu(duration_cap->tpm_long));
+
+ /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
+ * value wrong and apparently reports msecs rather than usecs. So we
+ * fix up the resulting too-small TPM_SHORT value to make things work.
+ */
+ if (chip->duration[TPM_SHORT] < MILLISECS(10)) {
+ chip->duration[TPM_SHORT] = SECONDS(1);
+ chip->duration[TPM_MEDIUM] *= 1000;
+ chip->duration[TPM_LONG] *= 1000;
+ printk("Adjusting TPM timeout parameters\n");
+ }
+
+ return 0;
+}
+
+
+
+void tpm_continue_selftest(struct tpm_chip* chip) {
+ uint8_t data[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 10, /* length */
+ 0, 0, 0, 83, /* TPM_ORD_GetCapability */
+ };
+
+ tpm_transmit(chip, data, sizeof(data));
+}
+
+ssize_t tpm_getcap(struct tpm_chip *chip, uint32_t subcap_id, cap_t *cap,
+ const char *desc)
+{
+ struct tpm_cmd_t tpm_cmd;
+ int rc;
+
+ tpm_cmd.header.in = tpm_getcap_header;
+ if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) {
+ tpm_cmd.params.getcap_in.cap = subcap_id;
+ /*subcap field not necessary */
+ tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(0);
+ tpm_cmd.header.in.length -= cpu_to_be32(sizeof(uint32_t));
+ } else {
+ if (subcap_id == TPM_CAP_FLAG_PERM ||
+ subcap_id == TPM_CAP_FLAG_VOL)
+ tpm_cmd.params.getcap_in.cap = TPM_CAP_FLAG;
+ else
+ tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
+ tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
+ tpm_cmd.params.getcap_in.subcap = subcap_id;
+ }
+ rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc);
+ if (!rc)
+ *cap = tpm_cmd.params.getcap_out.cap;
+ return rc;
+}
+
+
+struct tpm_chip* init_tpm_tis(unsigned long baseaddr, int localities, unsigned int irq)
+{
+ int i;
+ unsigned long addr;
+ struct tpm_chip* tpm = NULL;
+ uint32_t didvid;
+ uint32_t intfcaps;
+ uint32_t intmask;
+
+ printk("============= Init TPM TIS Driver ==============\n");
+
+ /*Sanity check the localities input */
+ if(localities & ~TPM_TIS_EN_LOCLALL) {
+ printk("init_tpm_tis() Invalid locality specification! %X\n", localities);
+ goto abort_egress;
+ }
+
+ printk("IOMEM Machine Base Address: %lX\n", baseaddr);
+
+ /* Create the tpm data structure */
+ tpm = malloc(sizeof(struct tpm_chip));
+ __init_tpm_chip(tpm);
+
+ /* Set the enabled localities - if 0 we leave default as all enabled */
+ if(localities != 0) {
+ tpm->enabled_localities = localities;
+ }
+ printk("Enabled Localities: ");
+ for(i = 0; i < 5; ++i) {
+ if(locality_enabled(tpm, i)) {
+ printk("%d ", i);
+ }
+ }
+ printk("\n");
+
+ /* Set the base machine address */
+ tpm->baseaddr = baseaddr;
+
+ /* Set default timeouts */
+ tpm->timeout_a = MILLISECS(TIS_SHORT_TIMEOUT);
+ tpm->timeout_b = MILLISECS(TIS_LONG_TIMEOUT);
+ tpm->timeout_c = MILLISECS(TIS_SHORT_TIMEOUT);
+ tpm->timeout_d = MILLISECS(TIS_SHORT_TIMEOUT);
+
+ /*Map the mmio pages */
+ addr = tpm->baseaddr;
+ for(i = 0; i < 5; ++i) {
+ if(locality_enabled(tpm, i)) {
+ /* Map the page in now */
+ if((tpm->pages[i] = ioremap_nocache(addr, PAGE_SIZE)) == NULL) {
+ printk("Unable to map iomem page a address %p\n", addr);
+ goto abort_egress;
+ }
+
+ /* Set default locality to the first enabled one */
+ if (tpm->locality < 0) {
+ if(tpm_tis_request_locality(tpm, i) < 0) {
+ printk("Unable to request locality %d??\n", i);
+ goto abort_egress;
+ }
+ }
+ }
+ addr += PAGE_SIZE;
+ }
+
+
+ /* Get the vendor and device ids */
+ didvid = ioread32(TPM_DID_VID(tpm, tpm->locality));
+ tpm->did = didvid >> 16;
+ tpm->vid = didvid & 0xFFFF;
+
+
+ /* Get the revision id */
+ tpm->rid = ioread8(TPM_RID(tpm, tpm->locality));
+
+ printk("1.2 TPM (device-id=0x%X vendor-id = %X rev-id = %X)\n", tpm->did, tpm->vid, tpm->rid);
+
+ intfcaps = ioread32(TPM_INTF_CAPS(tpm, tpm->locality));
+ printk("TPM interface capabilities (0x%x):\n", intfcaps);
+ if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
+ printk("\tBurst Count Static\n");
+ if (intfcaps & TPM_INTF_CMD_READY_INT)
+ printk("\tCommand Ready Int Support\n");
+ if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
+ printk("\tInterrupt Edge Falling\n");
+ if (intfcaps & TPM_INTF_INT_EDGE_RISING)
+ printk("\tInterrupt Edge Rising\n");
+ if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
+ printk("\tInterrupt Level Low\n");
+ if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
+ printk("\tInterrupt Level High\n");
+ if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
+ printk("\tLocality Change Int Support\n");
+ if (intfcaps & TPM_INTF_STS_VALID_INT)
+ printk("\tSts Valid Int Support\n");
+ if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
+ printk("\tData Avail Int Support\n");
+
+ /*Interupt setup */
+ intmask = ioread32(TPM_INT_ENABLE(tpm, tpm->locality));
+
+ intmask |= TPM_INTF_CMD_READY_INT
+ | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
+ | TPM_INTF_STS_VALID_INT;
+
+ iowrite32(TPM_INT_ENABLE(tpm, tpm->locality), intmask);
+
+ /*If interupts are enabled, handle it */
+ if(irq) {
+ if(irq != TPM_PROBE_IRQ) {
+ tpm->irq = irq;
+ } else {
+ /*FIXME add irq probing feature later */
+ printk("IRQ probing not implemented\n");
+ }
+ }
+
+ if(tpm->irq) {
+ iowrite8(TPM_INT_VECTOR(tpm, tpm->locality), tpm->irq);
+
+ if(bind_pirq(tpm->irq, 1, tpm_tis_irq_handler, tpm) != 0) {
+ printk("Unabled to request irq: %u for use\n", tpm->irq);
+ printk("Will use polling mode\n");
+ tpm->irq = 0;
+ } else {
+ /* Clear all existing */
+ iowrite32(TPM_INT_STATUS(tpm, tpm->locality), ioread32(TPM_INT_STATUS(tpm, tpm->locality)));
+
+ /* Turn on interrupts */
+ iowrite32(TPM_INT_ENABLE(tpm, tpm->locality), intmask | TPM_GLOBAL_INT_ENABLE);
+ }
+ }
+
+ if(tpm_get_timeouts(tpm)) {
+ printk("Could not get TPM timeouts and durations\n");
+ goto abort_egress;
+ }
+ tpm_continue_selftest(tpm);
+
+
+ return tpm;
+abort_egress:
+ if(tpm != NULL) {
+ shutdown_tpm_tis(tpm);
+ }
+ return NULL;
+}
+
+void shutdown_tpm_tis(struct tpm_chip* tpm){
+ int i;
+
+ printk("Shutting down tpm_tis device\n");
+
+ iowrite32(TPM_INT_ENABLE(tpm, tpm->locality), ~TPM_GLOBAL_INT_ENABLE);
+
+ /*Unmap all of the mmio pages */
+ for(i = 0; i < 5; ++i) {
+ if(tpm->pages[i] != NULL) {
+ iounmap(tpm->pages[i], PAGE_SIZE);
+ tpm->pages[i] = NULL;
+ }
+ }
+ free(tpm);
+ return;
+}
+
+
+int tpm_tis_cmd(struct tpm_chip* tpm, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen)
+{
+ if(tpm->locality < 0) {
+ printk("tpm_tis_cmd() failed! locality not set!\n");
+ return -1;
+ }
+ if(reqlen > TPM_BUFSIZE) {
+ reqlen = TPM_BUFSIZE;
+ }
+ memcpy(tpm->data_buffer, req, reqlen);
+ *resplen = tpm_transmit(tpm, tpm->data_buffer, TPM_BUFSIZE);
+
+ *resp = malloc(*resplen);
+ memcpy(*resp, tpm->data_buffer, *resplen);
+ return 0;
+}
+
+#ifdef HAVE_LIBC
+int tpm_tis_open(struct tpm_chip* tpm)
+{
+ /* Silently prevent multiple opens */
+ if(tpm->fd != -1) {
+ return tpm->fd;
+ }
+
+ tpm->fd = alloc_fd(FTYPE_TPM_TIS);
+ printk("tpm_tis_open() -> %d\n", tpm->fd);
+ files[tpm->fd].tpm_tis.dev = tpm;
+ files[tpm->fd].tpm_tis.offset = 0;
+ files[tpm->fd].tpm_tis.respgot = 0;
+ return tpm->fd;
+}
+
+int tpm_tis_posix_write(int fd, const uint8_t* buf, size_t count)
+{
+ struct tpm_chip* tpm;
+ tpm = files[fd].tpm_tis.dev;
+
+ if(tpm->locality < 0) {
+ printk("tpm_tis_posix_write() failed! locality not set!\n");
+ errno = EINPROGRESS;
+ return -1;
+ }
+ if(count == 0) {
+ return 0;
+ }
+
+ /* Return an error if we are already processing a command */
+ if(count > TPM_BUFSIZE) {
+ count = TPM_BUFSIZE;
+ }
+ /* Send the command now */
+ memcpy(tpm->data_buffer, buf, count);
+ if((tpm->data_len = tpm_transmit(tpm, tpm->data_buffer, TPM_BUFSIZE)) < 0) {
+ errno = EIO;
+ return -1;
+ }
+ return count;
+}
+
+int tpm_tis_posix_read(int fd, uint8_t* buf, size_t count)
+{
+ int rc;
+ struct tpm_chip* tpm;
+ tpm = files[fd].tpm_tis.dev;
+
+ if(count == 0) {
+ return 0;
+ }
+
+ /* If there is no tpm resp to read, return EIO */
+ if(tpm->data_len < 0) {
+ errno = EIO;
+ return -1;
+ }
+
+
+ /* Handle EOF case */
+ if(files[fd].tpm_tis.offset >= tpm->data_len) {
+ rc = 0;
+ } else {
+ rc = min(tpm->data_len - files[fd].tpm_tis.offset, count);
+ memcpy(buf, tpm->data_buffer + files[fd].tpm_tis.offset, rc);
+ }
+ files[fd].tpm_tis.offset += rc;
+ /* Reset the data pending flag */
+ return rc;
+}
+int tpm_tis_posix_fstat(int fd, struct stat* buf)
+{
+ struct tpm_chip* tpm;
+ tpm = files[fd].tpm_tis.dev;
+
+ buf->st_mode = O_RDWR;
+ buf->st_uid = 0;
+ buf->st_gid = 0;
+ buf->st_size = be32_to_cpu(*((uint32_t*)(tpm->data_buffer + 2)));
+ buf->st_atime = buf->st_mtime = buf->st_ctime = time(NULL);
+ return 0;
+}
+
+/* TPM 2.0 */
+
+/*TPM2.0 Selftest*/
+static void tpm2_selftest(struct tpm_chip* chip)
+{
+ uint8_t data[] = {
+ 0x80, 0x1,
+ 0x0, 0x0, 0x0, 0xb,
+ 0x0, 0x0, 0x1, 0x43,
+ 0x1,
+ };
+
+ tpm_transmit(chip, data, sizeof(data));
+}
+
+struct tpm_chip* init_tpm2_tis(unsigned long baseaddr, int localities, unsigned int irq)
+{
+ int i;
+ unsigned long addr;
+ struct tpm_chip* tpm = NULL;
+ uint32_t didvid;
+ uint32_t intfcaps;
+ uint32_t intmask;
+
+ printk("============= Init TPM2 TIS Driver ==============\n");
+
+ /*Sanity check the localities input */
+ if (localities & ~TPM_TIS_EN_LOCLALL) {
+ printk("init_tpm2_tis Invalid locality specification! %X\n", localities);
+ goto abort_egress;
+ }
+
+ printk("IOMEM Machine Base Address: %lX\n", baseaddr);
+
+ /* Create the tpm data structure */
+ tpm = malloc(sizeof(struct tpm_chip));
+ __init_tpm_chip(tpm);
+
+ /* Set the enabled localities - if 0 we leave default as all enabled */
+ if (localities != 0) {
+ tpm->enabled_localities = localities;
+ }
+ printk("Enabled Localities: ");
+ for (i = 0; i < 5; ++i) {
+ if (locality_enabled(tpm, i)) {
+ printk("%d ", i);
+ }
+ }
+ printk("\n");
+
+ /* Set the base machine address */
+ tpm->baseaddr = baseaddr;
+
+ /* Set default timeouts */
+ tpm->timeout_a = MILLISECS(TIS_SHORT_TIMEOUT);
+ tpm->timeout_b = MILLISECS(TIS_LONG_TIMEOUT);
+ tpm->timeout_c = MILLISECS(TIS_SHORT_TIMEOUT);
+ tpm->timeout_d = MILLISECS(TIS_SHORT_TIMEOUT);
+
+ /*Map the mmio pages */
+ addr = tpm->baseaddr;
+ for (i = 0; i < 5; ++i) {
+ if (locality_enabled(tpm, i)) {
+
+ /* Map the page in now */
+ if ((tpm->pages[i] = ioremap_nocache(addr, PAGE_SIZE)) == NULL) {
+ printk("Unable to map iomem page a address %p\n", addr);
+ goto abort_egress;
+ }
+
+ /* Set default locality to the first enabled one */
+ if (tpm->locality < 0) {
+ if (tpm_tis_request_locality(tpm, i) < 0) {
+ printk("Unable to request locality %d??\n", i);
+ goto abort_egress;
+ }
+ }
+ }
+ addr += PAGE_SIZE;
+ }
+
+ /* Get the vendor and device ids */
+ didvid = ioread32(TPM_DID_VID(tpm, tpm->locality));
+ tpm->did = didvid >> 16;
+ tpm->vid = didvid & 0xFFFF;
+
+ /* Get the revision id */
+ tpm->rid = ioread8(TPM_RID(tpm, tpm->locality));
+ printk("2.0 TPM (device-id=0x%X vendor-id = %X rev-id = %X)\n",
+ tpm->did, tpm->vid, tpm->rid);
+
+ intfcaps = ioread32(TPM_INTF_CAPS(tpm, tpm->locality));
+ printk("TPM interface capabilities (0x%x):\n", intfcaps);
+ if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
+ printk("\tBurst Count Static\n");
+ if (intfcaps & TPM_INTF_CMD_READY_INT)
+ printk("\tCommand Ready Int Support\n");
+ if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
+ printk("\tInterrupt Edge Falling\n");
+ if (intfcaps & TPM_INTF_INT_EDGE_RISING)
+ printk("\tInterrupt Edge Rising\n");
+ if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
+ printk("\tInterrupt Level Low\n");
+ if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
+ printk("\tInterrupt Level High\n");
+ if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
+ printk("\tLocality Change Int Support\n");
+ if (intfcaps & TPM_INTF_STS_VALID_INT)
+ printk("\tSts Valid Int Support\n");
+ if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
+ printk("\tData Avail Int Support\n");
+
+ /*Interupt setup */
+ intmask = ioread32(TPM_INT_ENABLE(tpm, tpm->locality));
+
+ intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
+ TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
+
+ iowrite32(TPM_INT_ENABLE(tpm, tpm->locality), intmask);
+
+ /*If interupts are enabled, handle it */
+ if (irq) {
+ if (irq != TPM_PROBE_IRQ) {
+ tpm->irq = irq;
+ } else {
+ /*FIXME add irq probing feature later */
+ printk("IRQ probing not implemented\n");
+ }
+ }
+
+ if (tpm->irq) {
+ iowrite8(TPM_INT_VECTOR(tpm, tpm->locality), tpm->irq);
+ if (bind_pirq(tpm->irq, 1, tpm_tis_irq_handler, tpm) != 0) {
+ printk("Unabled to request irq: %u for use\n", tpm->irq);
+ printk("Will use polling mode\n");
+ tpm->irq = 0;
+ } else {
+
+ /* Clear all existing */
+ iowrite32(TPM_INT_STATUS(tpm, tpm->locality),
+ ioread32(TPM_INT_STATUS(tpm, tpm->locality)));
+
+ /* Turn on interrupts */
+ iowrite32(TPM_INT_ENABLE(tpm, tpm->locality),
+ intmask | TPM_GLOBAL_INT_ENABLE);
+ }
+ }
+
+ tpm2_selftest(tpm);
+ return tpm;
+
+abort_egress:
+ if (tpm != NULL) {
+ shutdown_tpm_tis(tpm);
+ }
+ return NULL;
+}
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense. All rights reserved.
+ *
+ * This code has been derived from drivers/xen/tpmback/tpmback.c
+ * from the xen 2.6.18 linux kernel
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * which was itself derived from drivers/xen/netback/netback.c
+ * from the xen 2.6.18 linux kernel
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * This code has also been derived from drivers/xen/tpmback/xenbus.c
+ * from the xen 2.6.18 linux kernel
+ *
+ * Copyright (C) 2005 IBM Corporation
+ * Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
+ *
+ * This code has also been derived from drivers/xen/tpmback/interface.c
+ * from the xen 2.6.18 linux kernel
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * which was itself also derived from drvivers/xen/netback/interface.c
+ * from the xen 2.6.18 linux kernel
+ *
+ * Copyright (c) 2004, Keir Fraser
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, version 2
+ * of the License
+ */
+#include <mini-os/os.h>
+#include <mini-os/xenbus.h>
+#include <mini-os/events.h>
+#include <errno.h>
+#include <mini-os/gnttab.h>
+#include <xen/io/xenbus.h>
+#include <xen/io/tpmif.h>
+#include <xen/io/protocols.h>
+#include <mini-os/xmalloc.h>
+#include <time.h>
+#include <mini-os/tpmback.h>
+#include <mini-os/lib.h>
+#include <fcntl.h>
+#include <mini-os/mm.h>
+#include <mini-os/posix/sys/mman.h>
+#include <mini-os/semaphore.h>
+#include <mini-os/wait.h>
+
+
+#ifndef HAVE_LIBC
+#define strtoul simple_strtoul
+#endif
+
+//#define TPMBACK_PRINT_DEBUG
+#ifdef TPMBACK_PRINT_DEBUG
+#define TPMBACK_DEBUG(fmt,...) printk("Tpmback:Debug("__FILE__":%d) " fmt, __LINE__, ##__VA_ARGS__)
+#define TPMBACK_DEBUG_MORE(fmt,...) printk(fmt, ##__VA_ARGS__)
+#else
+#define TPMBACK_DEBUG(fmt,...)
+#endif
+#define TPMBACK_ERR(fmt,...) printk("Tpmback:Error " fmt, ##__VA_ARGS__)
+#define TPMBACK_LOG(fmt,...) printk("Tpmback:Info " fmt, ##__VA_ARGS__)
+
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+
+/* Default size of the tpmif array at initialization */
+#define DEF_ARRAY_SIZE 1
+
+/* tpmif and tpmdev flags */
+#define TPMIF_CLOSED 1
+#define TPMIF_REQ_READY 2
+
+struct tpmif {
+ domid_t domid;
+ unsigned int handle;
+
+ char* fe_path;
+ char* fe_state_path;
+
+ /* Locally bound event channel*/
+ evtchn_port_t evtchn;
+
+ /* Shared page */
+ tpmif_shared_page_t *page;
+
+ enum xenbus_state state;
+ enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
+
+ unsigned char uuid[16];
+ void* opaque;
+
+ /* state flags */
+ int flags;
+};
+typedef struct tpmif tpmif_t;
+
+struct tpmback_dev {
+
+ tpmif_t** tpmlist;
+ unsigned long num_tpms;
+ unsigned long num_alloc;
+
+ struct gntmap map;
+
+ /* True if at least one tpmif has a request to be handled */
+ int flags;
+
+ xenbus_event_queue events;
+
+ /* Callbacks */
+ void (*open_callback)(domid_t, unsigned int);
+ void (*close_callback)(domid_t, unsigned int);
+};
+typedef struct tpmback_dev tpmback_dev_t;
+
+enum { EV_NONE, EV_NEWFE, EV_STCHNG } tpm_ev_enum;
+
+/* Global objects */
+static struct thread* eventthread = NULL;
+static tpmback_dev_t gtpmdev = {
+ .tpmlist = NULL,
+ .num_tpms = 0,
+ .num_alloc = 0,
+ .flags = TPMIF_CLOSED,
+ .events = NULL,
+ .open_callback = NULL,
+ .close_callback = NULL,
+};
+struct wait_queue_head waitq;
+int globalinit = 0;
+
+/************************************
+ * TPMIF SORTED ARRAY FUNCTIONS
+ * tpmback_dev_t.tpmlist is a sorted array, sorted by domid and then handle number
+ * Duplicates are not allowed
+ * **********************************/
+
+static void tpmif_req_ready(tpmif_t* tpmif) {
+ tpmif->flags |= TPMIF_REQ_READY;
+ gtpmdev.flags |= TPMIF_REQ_READY;
+}
+
+static void tpmdev_check_req(void) {
+ int i;
+ int flags;
+ local_irq_save(flags);
+ for(i = 0; i < gtpmdev.num_tpms; ++i) {
+ if(gtpmdev.tpmlist[i]->flags & TPMIF_REQ_READY) {
+ gtpmdev.flags |= TPMIF_REQ_READY;
+ local_irq_restore(flags);
+ return;
+ }
+ }
+ gtpmdev.flags &= ~TPMIF_REQ_READY;
+ local_irq_restore(flags);
+}
+
+static void tpmif_req_finished(tpmif_t* tpmif) {
+ tpmif->flags &= ~TPMIF_REQ_READY;
+ tpmdev_check_req();
+}
+
+int __get_tpmif_index(int st, int n, domid_t domid, unsigned int handle)
+{
+ int i = st + n /2;
+ tpmif_t* tmp;
+
+ if( n <= 0 )
+ return -1;
+
+ tmp = gtpmdev.tpmlist[i];
+ if(domid == tmp->domid && tmp->handle == handle) {
+ return i;
+ } else if ( (domid < tmp->domid) ||
+ (domid == tmp->domid && handle < tmp->handle)) {
+ return __get_tpmif_index(st, n/2, domid, handle);
+ } else {
+ return __get_tpmif_index(i + 1, n/2 - ((n +1) % 2), domid, handle);
+ }
+}
+
+/* Returns the array index of the tpmif domid/handle. Returns -1 if no such tpmif exists */
+int get_tpmif_index(domid_t domid, unsigned int handle)
+{
+ int flags;
+ int index;
+ local_irq_save(flags);
+ index = __get_tpmif_index(0, gtpmdev.num_tpms, domid, handle);
+ local_irq_restore(flags);
+ return index;
+}
+
+/* Returns the tpmif domid/handle or NULL if none exists */
+tpmif_t* get_tpmif(domid_t domid, unsigned int handle)
+{
+ int flags;
+ int i;
+ tpmif_t* ret;
+ local_irq_save(flags);
+ i = get_tpmif_index(domid, handle);
+ if (i < 0) {
+ ret = NULL;
+ } else {
+ ret = gtpmdev.tpmlist[i];
+ }
+ local_irq_restore(flags);
+ return ret;
+}
+
+/* Remove the given tpmif. Returns 0 if it was removed, -1 if it was not removed */
+int remove_tpmif(tpmif_t* tpmif)
+{
+ int i, j;
+ char* err;
+ int flags;
+ local_irq_save(flags);
+
+ /* Find the index in the array if it exists */
+ i = get_tpmif_index(tpmif->domid, tpmif->handle);
+ if (i < 0) {
+ goto error;
+ }
+
+ /* Remove the interface from the list */
+ for(j = i; j < gtpmdev.num_tpms - 1; ++j) {
+ gtpmdev.tpmlist[j] = gtpmdev.tpmlist[j+1];
+ }
+ gtpmdev.tpmlist[j] = NULL;
+ --gtpmdev.num_tpms;
+
+ /* If removed tpm was the only ready tpm, then we need to check and turn off the ready flag */
+ tpmdev_check_req();
+
+ local_irq_restore(flags);
+
+ /* Stop listening for events on this tpm interface */
+ if((err = xenbus_unwatch_path_token(XBT_NIL, tpmif->fe_state_path, tpmif->fe_state_path))) {
+ TPMBACK_ERR("Unable to unwatch path token `%s' Error was %s Ignoring..\n", tpmif->fe_state_path, err);
+ free(err);
+ }
+
+ return 0;
+error:
+ local_irq_restore(flags);
+ return -1;
+}
+
+/* Insert tpmif into dev->tpmlist. Returns 0 on success and non zero on error.
+ * It is an error to insert a tpmif with the same domid and handle
+ * number
+ * as something already in the list */
+int insert_tpmif(tpmif_t* tpmif)
+{
+ int flags;
+ unsigned int i, j;
+ tpmif_t* tmp;
+ char* err;
+ char path[512];
+
+ local_irq_save(flags);
+
+ /*Check if we need to allocate more space */
+ if (gtpmdev.num_tpms == gtpmdev.num_alloc) {
+ gtpmdev.num_alloc *= 2;
+ gtpmdev.tpmlist = realloc(gtpmdev.tpmlist, gtpmdev.num_alloc);
+ }
+
+ /*Find where to put the new interface */
+ for(i = 0; i < gtpmdev.num_tpms; ++i)
+ {
+ tmp = gtpmdev.tpmlist[i];
+ if(tpmif->domid == tmp->domid && tpmif->handle == tmp->handle) {
+ TPMBACK_ERR("Tried to insert duplicate tpm interface %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
+ goto error;
+ }
+ if((tpmif->domid < tmp->domid) ||
+ (tpmif->domid == tmp->domid && tpmif->handle < tmp->handle)) {
+ break;
+ }
+ }
+
+ /*Shift all the tpm pointers past i down one */
+ for(j = gtpmdev.num_tpms; j > i; --j) {
+ gtpmdev.tpmlist[j] = gtpmdev.tpmlist[j-1];
+ }
+
+ /*Add the new interface */
+ gtpmdev.tpmlist[i] = tpmif;
+ ++gtpmdev.num_tpms;
+
+ /*Should not be needed, anything inserted with ready flag is probably an error */
+ tpmdev_check_req();
+
+ local_irq_restore(flags);
+
+ snprintf(path, 512, "backend/vtpm/%u/%u/feature-protocol-v2", (unsigned int) tpmif->domid, tpmif->handle);
+ if ((err = xenbus_write(XBT_NIL, path, "1")))
+ {
+ /* if we got an error here we should carefully remove the interface and then return */
+ TPMBACK_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
+ free(err);
+ remove_tpmif(tpmif);
+ goto error_post_irq;
+ }
+
+ /*Listen for state changes on the new interface */
+ if((err = xenbus_watch_path_token(XBT_NIL, tpmif->fe_state_path, tpmif->fe_state_path, >pmdev.events)))
+ {
+ /* if we got an error here we should carefully remove the interface and then return */
+ TPMBACK_ERR("Unable to watch path token `%s' Error was %s\n", tpmif->fe_state_path, err);
+ free(err);
+ remove_tpmif(tpmif);
+ goto error_post_irq;
+ }
+ return 0;
+error:
+ local_irq_restore(flags);
+error_post_irq:
+ return -1;
+}
+
+
+/*****************
+ * CHANGE BACKEND STATE
+ * *****************/
+/*Attempts to change the backend state in xenstore
+ * returns 0 on success and non-zero on error */
+int tpmif_change_state(tpmif_t* tpmif, enum xenbus_state state)
+{
+ int tempst;
+ char path[512];
+ char *value;
+ char *err;
+ enum xenbus_state readst;
+ TPMBACK_DEBUG("Backend state change %u/%u from=%d to=%d\n", (unsigned int) tpmif->domid, tpmif->handle, tpmif->state, state);
+ if (tpmif->state == state)
+ return 0;
+
+ snprintf(path, 512, "backend/vtpm/%u/%u/state", (unsigned int) tpmif->domid, tpmif->handle);
+
+ if((err = xenbus_read(XBT_NIL, path, &value))) {
+ TPMBACK_ERR("Unable to read backend state %s, error was %s\n", path, err);
+ free(err);
+ return -1;
+ }
+ if(sscanf(value, "%d", &tempst) != 1) {
+ TPMBACK_ERR("Non integer value (%s) in %s ??\n", value, path);
+ free(value);
+ return -1;
+ }
+ readst = (enum xenbus_state) tempst;
+ free(value);
+
+ /* It's possible that the backend state got updated by hotplug or something else behind our back */
+ if(readst != tpmif->state) {
+ TPMBACK_DEBUG("tpm interface state was %d but xenstore state was %d!\n", tpmif->state, readst);
+ tpmif->state = readst;
+ }
+
+ /*If if the state isnt changing, then we dont update xenstore b/c we dont want to fire extraneous events */
+ if(tpmif->state == state) {
+ return 0;
+ }
+
+ /*update xenstore*/
+ snprintf(path, 512, "backend/vtpm/%u/%u", (unsigned int) tpmif->domid, tpmif->handle);
+ if((err = xenbus_printf(XBT_NIL, path, "state", "%u", state))) {
+ TPMBACK_ERR("Error writing to xenstore %s, error was %s new state=%d\n", path, err, state);
+ free(err);
+ return -1;
+ }
+
+ tpmif->state = state;
+
+ return 0;
+}
+/**********************************
+ * TPMIF CREATION AND DELETION
+ * *******************************/
+static tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
+{
+ tpmif_t* tpmif;
+ tpmif = malloc(sizeof(*tpmif));
+ tpmif->domid = domid;
+ tpmif->handle = handle;
+ tpmif->fe_path = NULL;
+ tpmif->fe_state_path = NULL;
+ tpmif->state = XenbusStateInitialising;
+ tpmif->status = DISCONNECTED;
+ tpmif->page = NULL;
+ tpmif->flags = 0;
+ tpmif->opaque = NULL;
+ memset(tpmif->uuid, 0, sizeof(tpmif->uuid));
+ return tpmif;
+}
+
+void __free_tpmif(tpmif_t* tpmif)
+{
+ if(tpmif->fe_path) {
+ free(tpmif->fe_path);
+ }
+ if(tpmif->fe_state_path) {
+ free(tpmif->fe_state_path);
+ }
+ free(tpmif);
+}
+/* Creates a new tpm interface, adds it to the sorted array and returns it.
+ * returns NULL on error
+ * If the tpm interface already exists, it is returned*/
+tpmif_t* new_tpmif(domid_t domid, unsigned int handle)
+{
+ tpmif_t* tpmif;
+ char* err;
+ char path[512];
+
+ /* Make sure we haven't already created this tpm
+ * Double events can occur */
+ if((tpmif = get_tpmif(domid, handle)) != NULL) {
+ return tpmif;
+ }
+
+ tpmif = __init_tpmif(domid, handle);
+
+ /* Get the uuid from xenstore */
+ snprintf(path, 512, "backend/vtpm/%u/%u/uuid", (unsigned int) domid, handle);
+ if((!xenbus_read_uuid(path, tpmif->uuid))) {
+ TPMBACK_ERR("Error reading %s\n", path);
+ goto error;
+ }
+
+ if(tpmif_change_state(tpmif, XenbusStateInitWait)) {
+ goto error;
+ }
+
+ snprintf(path, 512, "backend/vtpm/%u/%u/frontend", (unsigned int) domid, handle);
+ if((err = xenbus_read(XBT_NIL, path, &tpmif->fe_path))) {
+ TPMBACK_ERR("Error creating new tpm instance xenbus_read(%s), Error = %s", path, err);
+ free(err);
+ goto error;
+ }
+
+ /*Set the state path */
+ tpmif->fe_state_path = malloc(strlen(tpmif->fe_path) + 7);
+ strcpy(tpmif->fe_state_path, tpmif->fe_path);
+ strcat(tpmif->fe_state_path, "/state");
+
+ if(insert_tpmif(tpmif)) {
+ goto error;
+ }
+ TPMBACK_DEBUG("New tpmif %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
+ /* Do the callback now */
+ if(gtpmdev.open_callback) {
+ gtpmdev.open_callback(tpmif->domid, tpmif->handle);
+ }
+ return tpmif;
+error:
+ __free_tpmif(tpmif);
+ return NULL;
+
+}
+
+/* Removes tpmif from dev->tpmlist and frees it's memory usage */
+void free_tpmif(tpmif_t* tpmif)
+{
+ char* err;
+ char path[512];
+ TPMBACK_DEBUG("Free tpmif %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
+ if(tpmif->flags & TPMIF_CLOSED) {
+ TPMBACK_ERR("Tried to free an instance twice! Theres a bug somewhere!\n");
+ BUG();
+ }
+ tpmif->flags = TPMIF_CLOSED;
+
+ tpmif_change_state(tpmif, XenbusStateClosing);
+
+ /* Unmap share page and unbind event channel */
+ if(tpmif->status == CONNECTED) {
+ tpmif->status = DISCONNECTING;
+ mask_evtchn(tpmif->evtchn);
+
+ if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
+ TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
+ }
+
+ unbind_evtchn(tpmif->evtchn);
+ }
+ tpmif->status = DISCONNECTED;
+ tpmif_change_state(tpmif, XenbusStateClosed);
+
+ /* Do the callback now */
+ if(gtpmdev.close_callback) {
+ gtpmdev.close_callback(tpmif->domid, tpmif->handle);
+ }
+
+ /* remove from array */
+ remove_tpmif(tpmif);
+
+ /* Wake up anyone possibly waiting on this interface and let them exit */
+ wake_up(&waitq);
+ schedule();
+
+ /* Remove the old xenbus entries */
+ snprintf(path, 512, "backend/vtpm/%u/%u", (unsigned int) tpmif->domid, tpmif->handle);
+ if((err = xenbus_rm(XBT_NIL, path))) {
+ TPMBACK_ERR("Error cleaning up xenbus entries path=%s error=%s\n", path, err);
+ free(err);
+ }
+
+ TPMBACK_LOG("Frontend %u/%u disconnected\n", (unsigned int) tpmif->domid, tpmif->handle);
+
+ /* free memory */
+ __free_tpmif(tpmif);
+
+}
+
+/**********************
+ * REMAINING TPMBACK FUNCTIONS
+ * ********************/
+
+/*Event channel handler */
+void tpmback_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+ tpmif_t* tpmif = (tpmif_t*) data;
+ tpmif_shared_page_t *pg = tpmif->page;
+
+ switch (pg->state)
+ {
+ case TPMIF_STATE_SUBMIT:
+ TPMBACK_DEBUG("EVENT CHANNEL FIRE %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
+ tpmif_req_ready(tpmif);
+ wake_up(&waitq);
+ break;
+ case TPMIF_STATE_CANCEL:
+ /* If we are busy with a request, do nothing */
+ if (tpmif->flags & TPMIF_REQ_READY)
+ return;
+ /* Acknowledge the cancellation if we are idle */
+ pg->state = TPMIF_STATE_IDLE;
+ wmb();
+ notify_remote_via_evtchn(tpmif->evtchn);
+ return;
+ default:
+ /* Spurious wakeup; do nothing */
+ return;
+ }
+}
+
+/* Connect to frontend */
+int connect_fe(tpmif_t* tpmif)
+{
+ char path[512];
+ char* err, *value;
+ uint32_t domid;
+ grant_ref_t ringref;
+ evtchn_port_t evtchn;
+
+ /* If already connected then quit */
+ if (tpmif->status == CONNECTED) {
+ TPMBACK_DEBUG("%u/%u tried to connect while it was already connected?\n", (unsigned int) tpmif->domid, tpmif->handle);
+ return 0;
+ }
+
+ /* Fetch the grant reference */
+ snprintf(path, 512, "%s/ring-ref", tpmif->fe_path);
+ if((err = xenbus_read(XBT_NIL, path, &value))) {
+ TPMBACK_ERR("Error creating new tpm instance xenbus_read(%s) Error = %s", path, err);
+ free(err);
+ return -1;
+ }
+ if(sscanf(value, "%d", &ringref) != 1) {
+ TPMBACK_ERR("Non integer value (%s) in %s ??\n", value, path);
+ free(value);
+ return -1;
+ }
+ free(value);
+
+
+ /* Fetch the event channel*/
+ snprintf(path, 512, "%s/event-channel", tpmif->fe_path);
+ if((err = xenbus_read(XBT_NIL, path, &value))) {
+ TPMBACK_ERR("Error creating new tpm instance xenbus_read(%s) Error = %s", path, err);
+ free(err);
+ return -1;
+ }
+ if(sscanf(value, "%d", &evtchn) != 1) {
+ TPMBACK_ERR("Non integer value (%s) in %s ??\n", value, path);
+ free(value);
+ return -1;
+ }
+ free(value);
+
+ /* Check that protocol v2 is being used */
+ snprintf(path, 512, "%s/feature-protocol-v2", tpmif->fe_path);
+ if((err = xenbus_read(XBT_NIL, path, &value))) {
+ TPMBACK_ERR("Unable to read %s during tpmback initialization! error = %s\n", path, err);
+ free(err);
+ return -1;
+ }
+ if(strcmp(value, "1")) {
+ TPMBACK_ERR("%s has an invalid value (%s)\n", path, value);
+ free(value);
+ return -1;
+ }
+ free(value);
+
+ domid = tpmif->domid;
+ if((tpmif->page = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
+ TPMBACK_ERR("Failed to map grant reference %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
+ return -1;
+ }
+
+ /*Bind the event channel */
+ if((evtchn_bind_interdomain(tpmif->domid, evtchn, tpmback_handler, tpmif, &tpmif->evtchn)))
+ {
+ TPMBACK_ERR("%u/%u Unable to bind to interdomain event channel!\n", (unsigned int) tpmif->domid, tpmif->handle);
+ goto error_post_map;
+ }
+ unmask_evtchn(tpmif->evtchn);
+
+ /* Write the ready flag and change status to connected */
+ snprintf(path, 512, "backend/vtpm/%u/%u", (unsigned int) tpmif->domid, tpmif->handle);
+ if((err = xenbus_printf(XBT_NIL, path, "ready", "%u", 1))) {
+ TPMBACK_ERR("%u/%u Unable to write ready flag on connect_fe()\n", (unsigned int) tpmif->domid, tpmif->handle);
+ free(err);
+ goto error_post_evtchn;
+ }
+ tpmif->status = CONNECTED;
+ if((tpmif_change_state(tpmif, XenbusStateConnected))){
+ goto error_post_evtchn;
+ }
+
+ TPMBACK_LOG("Frontend %u/%u connected\n", (unsigned int) tpmif->domid, tpmif->handle);
+
+ return 0;
+error_post_evtchn:
+ mask_evtchn(tpmif->evtchn);
+ unbind_evtchn(tpmif->evtchn);
+error_post_map:
+ gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1);
+ return -1;
+}
+
+static void disconnect_fe(tpmif_t* tpmif)
+{
+ if (tpmif->status == CONNECTED) {
+ tpmif->status = DISCONNECTING;
+ mask_evtchn(tpmif->evtchn);
+
+ if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
+ TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
+ }
+
+ unbind_evtchn(tpmif->evtchn);
+ }
+ tpmif->status = DISCONNECTED;
+ tpmif_change_state(tpmif, XenbusStateInitWait);
+
+ TPMBACK_LOG("Frontend %u/%u disconnected\n", (unsigned int) tpmif->domid, tpmif->handle);
+}
+
+static int frontend_changed(tpmif_t* tpmif)
+{
+ int state = xenbus_read_integer(tpmif->fe_state_path);
+ if(state < 0) {
+ state = XenbusStateUnknown;
+ }
+
+ TPMBACK_DEBUG("Frontend %u/%u state changed to %d\n", (unsigned int) tpmif->domid, tpmif->handle, state);
+
+ switch (state) {
+ case XenbusStateInitialising:
+ break;
+
+ case XenbusStateInitialised:
+ case XenbusStateConnected:
+ if(connect_fe(tpmif)) {
+ TPMBACK_ERR("Failed to connect to front end %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
+ tpmif_change_state(tpmif, XenbusStateClosed);
+ return -1;
+ }
+ break;
+
+ case XenbusStateClosing:
+ tpmif_change_state(tpmif, XenbusStateClosing);
+ break;
+
+ case XenbusStateClosed:
+ disconnect_fe(tpmif);
+ break;
+
+ case XenbusStateUnknown: /* keep it here */
+ free_tpmif(tpmif);
+ break;
+
+ default:
+ TPMBACK_DEBUG("BAD STATE CHANGE %u/%u state = %d for tpmif\n", (unsigned int) tpmif->domid, tpmif->handle, state);
+ return -1;
+ }
+ return 0;
+}
+
+
+/* parses the string that comes out of xenbus_watch_wait_return. */
+static int parse_eventstr(const char* evstr, domid_t* domid, unsigned int* handle)
+{
+ int ret;
+ char cmd[40];
+ char* err;
+ char* value;
+ unsigned int udomid = 0;
+ tpmif_t* tpmif;
+ /* First check for new frontends, this occurs when /backend/vtpm/<domid>/<handle> gets created. Note we what the sscanf to fail on the last %s */
+ if (sscanf(evstr, "backend/vtpm/%u/%u/%40s", &udomid, handle, cmd) == 2) {
+ *domid = udomid;
+ /* Make sure the entry exists, if this event triggers because the entry dissapeared then ignore it */
+ if((err = xenbus_read(XBT_NIL, evstr, &value))) {
+ free(err);
+ return EV_NONE;
+ }
+ free(value);
+ /* Make sure the tpmif entry does not already exist, this should not happen */
+ if((tpmif = get_tpmif(*domid, *handle)) != NULL) {
+ TPMBACK_DEBUG("Duplicate tpm entries! %u %u\n", tpmif->domid, tpmif->handle);
+ return EV_NONE;
+ }
+ return EV_NEWFE;
+ } else if((ret = sscanf(evstr, "/local/domain/%u/device/vtpm/%u/%40s", &udomid, handle, cmd)) == 3) {
+ *domid = udomid;
+ if (!strcmp(cmd, "state"))
+ return EV_STCHNG;
+ }
+ return EV_NONE;
+}
+
+void handle_backend_event(char* evstr) {
+ tpmif_t* tpmif;
+ domid_t domid;
+ unsigned int handle;
+ int event;
+
+ TPMBACK_DEBUG("Xenbus Event: %s\n", evstr);
+
+ event = parse_eventstr(evstr, &domid, &handle);
+
+ switch(event) {
+ case EV_NEWFE:
+ if(new_tpmif(domid, handle) == NULL) {
+ TPMBACK_ERR("Failed to create new tpm instance %u/%u\n", (unsigned int) domid, handle);
+ }
+ wake_up(&waitq);
+ break;
+ case EV_STCHNG:
+ if((tpmif = get_tpmif(domid, handle))) {
+ frontend_changed(tpmif);
+ } else {
+ TPMBACK_DEBUG("Event Received for non-existant tpm! instance=%u/%u xenbus_event=%s\n", (unsigned int) domid, handle, evstr);
+ }
+ break;
+ }
+}
+
+/* Runs through the given path and creates events recursively
+ * for all of its children.
+ * @path - xenstore path to scan */
+static void generate_backend_events(const char* path)
+{
+ char* err;
+ int i, len;
+ char **dirs;
+ char *entry;
+
+ if((err = xenbus_ls(XBT_NIL, path, &dirs)) != NULL) {
+ free(err);
+ return;
+ }
+
+ for(i = 0; dirs[i] != NULL; ++i) {
+ len = strlen(path) + strlen(dirs[i]) + 2;
+ entry = malloc(len);
+ snprintf(entry, len, "%s/%s", path, dirs[i]);
+
+ /* Generate and handle event for the entry itself */
+ handle_backend_event(entry);
+
+ /* Do children */
+ generate_backend_events(entry);
+
+ /* Cleanup */
+ free(entry);
+ free(dirs[i]);
+ }
+ free(dirs);
+ return;
+}
+
+void* tpmback_get_opaque(domid_t domid, unsigned int handle)
+{
+ tpmif_t* tpmif;
+ if((tpmif = get_tpmif(domid, handle)) == NULL) {
+ TPMBACK_DEBUG("get_opaque() failed, %u/%u is an invalid frontend\n", (unsigned int) domid, handle);
+ return NULL;
+ }
+
+ return tpmif->opaque;
+}
+
+int tpmback_set_opaque(domid_t domid, unsigned int handle, void *opaque)
+{
+ tpmif_t* tpmif;
+ if((tpmif = get_tpmif(domid, handle)) == NULL) {
+ TPMBACK_DEBUG("set_opaque() failed, %u/%u is an invalid frontend\n", (unsigned int) domid, handle);
+ return -1;
+ }
+
+ tpmif->opaque = opaque;
+ return 0;
+}
+
+unsigned char* tpmback_get_uuid(domid_t domid, unsigned int handle)
+{
+ tpmif_t* tpmif;
+ if((tpmif = get_tpmif(domid, handle)) == NULL) {
+ TPMBACK_DEBUG("get_uuid() failed, %u/%u is an invalid frontend\n", (unsigned int) domid, handle);
+ return NULL;
+ }
+
+ return tpmif->uuid;
+}
+
+int tpmback_get_peercontext(domid_t domid, unsigned int handle, void* buffer, int buflen)
+{
+ tpmif_t* tpmif;
+ if((tpmif = get_tpmif(domid, handle)) == NULL) {
+ TPMBACK_DEBUG("get_uuid() failed, %u/%u is an invalid frontend\n", (unsigned int) domid, handle);
+ return -1;
+ }
+
+ return evtchn_get_peercontext(tpmif->evtchn, buffer, buflen);
+}
+
+static void event_listener(void)
+{
+ const char* bepath = "backend/vtpm";
+ char **path;
+ char* err;
+
+ /* Setup the backend device watch */
+ if((err = xenbus_watch_path_token(XBT_NIL, bepath, bepath, >pmdev.events)) != NULL) {
+ TPMBACK_ERR("xenbus_watch_path_token(%s) failed with error %s!\n", bepath, err);
+ free(err);
+ goto egress;
+ }
+
+ /* Check for any frontends that connected before we set the watch.
+ * This is almost guaranteed to happen if both domains are started
+ * immediatly one after the other.
+ * We do this by manually generating events on everything in the backend
+ * path */
+ generate_backend_events(bepath);
+
+ /* Wait and listen for changes in frontend connections */
+ while(1) {
+ path = xenbus_wait_for_watch_return(>pmdev.events);
+
+ /*If quit flag was set then exit */
+ if(gtpmdev.flags & TPMIF_CLOSED) {
+ TPMBACK_DEBUG("listener thread got quit event. Exiting..\n");
+ free(path);
+ break;
+ }
+ handle_backend_event(*path);
+ free(path);
+
+ }
+
+ if((err = xenbus_unwatch_path_token(XBT_NIL, bepath, bepath)) != NULL) {
+ free(err);
+ }
+egress:
+ return;
+}
+
+void event_thread(void* p) {
+ event_listener();
+}
+
+void init_tpmback(void (*open_cb)(domid_t, unsigned int), void (*close_cb)(domid_t, unsigned int))
+{
+ if(!globalinit) {
+ init_waitqueue_head(&waitq);
+ globalinit = 1;
+ }
+ printk("============= Init TPM BACK ================\n");
+ gtpmdev.tpmlist = malloc(sizeof(tpmif_t*) * DEF_ARRAY_SIZE);
+ gtpmdev.num_alloc = DEF_ARRAY_SIZE;
+ gtpmdev.num_tpms = 0;
+ gtpmdev.flags = 0;
+
+ gtpmdev.open_callback = open_cb;
+ gtpmdev.close_callback = close_cb;
+
+ eventthread = create_thread("tpmback-listener", event_thread, NULL);
+
+}
+
+void shutdown_tpmback(void)
+{
+ TPMBACK_LOG("Shutting down tpm backend\n");
+ /* Set the quit flag */
+ gtpmdev.flags = TPMIF_CLOSED;
+
+ //printk("num tpms is %d\n", gtpmdev.num_tpms);
+ /*Free all backend instances */
+ while(gtpmdev.num_tpms) {
+ free_tpmif(gtpmdev.tpmlist[0]);
+ }
+ free(gtpmdev.tpmlist);
+ gtpmdev.tpmlist = NULL;
+ gtpmdev.num_alloc = 0;
+
+ /* Wake up anyone possibly waiting on the device and let them exit */
+ wake_up(&waitq);
+ schedule();
+}
+
+static void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, void *opaque)
+{
+ tpmcmd->domid = domid;
+ tpmcmd->locality = -1;
+ tpmcmd->handle = handle;
+ tpmcmd->opaque = opaque;
+ tpmcmd->req = NULL;
+ tpmcmd->req_len = 0;
+ tpmcmd->resp = NULL;
+ tpmcmd->resp_len = 0;
+}
+
+tpmcmd_t* get_request(tpmif_t* tpmif) {
+ tpmcmd_t* cmd;
+ tpmif_shared_page_t *shr;
+ unsigned int offset;
+ int flags;
+#ifdef TPMBACK_PRINT_DEBUG
+ int i;
+#endif
+
+ local_irq_save(flags);
+
+ /* Allocate the cmd object to hold the data */
+ if((cmd = malloc(sizeof(*cmd))) == NULL) {
+ goto error;
+ }
+ init_tpmcmd(cmd, tpmif->domid, tpmif->handle, tpmif->opaque);
+
+ shr = tpmif->page;
+ cmd->req_len = shr->length;
+ cmd->locality = shr->locality;
+ offset = sizeof(*shr) + 4*shr->nr_extra_pages;
+ if (offset > PAGE_SIZE || offset + cmd->req_len > PAGE_SIZE) {
+ TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
+ goto error;
+ }
+ /* Allocate the buffer */
+ if(cmd->req_len) {
+ if((cmd->req = malloc(cmd->req_len)) == NULL) {
+ goto error;
+ }
+ }
+ /* Copy the bits from the shared page(s) */
+ memcpy(cmd->req, offset + (uint8_t*)shr, cmd->req_len);
+
+#ifdef TPMBACK_PRINT_DEBUG
+ TPMBACK_DEBUG("Received Tpm Command from %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->req_len);
+ for(i = 0; i < cmd->req_len; ++i) {
+ if (!(i % 30)) {
+ TPMBACK_DEBUG_MORE("\n");
+ }
+ TPMBACK_DEBUG_MORE("%02hhX ", cmd->req[i]);
+ }
+ TPMBACK_DEBUG_MORE("\n\n");
+#endif
+
+ local_irq_restore(flags);
+ return cmd;
+error:
+ if(cmd != NULL) {
+ if (cmd->req != NULL) {
+ free(cmd->req);
+ cmd->req = NULL;
+ }
+ free(cmd);
+ cmd = NULL;
+ }
+ local_irq_restore(flags);
+ return NULL;
+
+}
+
+void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
+{
+ tpmif_shared_page_t *shr;
+ unsigned int offset;
+ int flags;
+#ifdef TPMBACK_PRINT_DEBUG
+int i;
+#endif
+
+ local_irq_save(flags);
+
+ shr = tpmif->page;
+ shr->length = cmd->resp_len;
+
+ offset = sizeof(*shr) + 4*shr->nr_extra_pages;
+ if (offset > PAGE_SIZE || offset + cmd->resp_len > PAGE_SIZE) {
+ TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
+ goto error;
+ }
+ memcpy(offset + (uint8_t*)shr, cmd->resp, cmd->resp_len);
+
+#ifdef TPMBACK_PRINT_DEBUG
+ TPMBACK_DEBUG("Sent response to %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->resp_len);
+ for(i = 0; i < cmd->resp_len; ++i) {
+ if (!(i % 30)) {
+ TPMBACK_DEBUG_MORE("\n");
+ }
+ TPMBACK_DEBUG_MORE("%02hhX ", cmd->resp[i]);
+ }
+ TPMBACK_DEBUG_MORE("\n\n");
+#endif
+ /* clear the ready flag and send the event channel notice to the frontend */
+ tpmif_req_finished(tpmif);
+ barrier();
+ shr->state = TPMIF_STATE_FINISH;
+ wmb();
+ notify_remote_via_evtchn(tpmif->evtchn);
+error:
+ local_irq_restore(flags);
+ return;
+}
+
+tpmcmd_t* tpmback_req_any(void)
+{
+ int i;
+ /* Block until something has a request */
+ wait_event(waitq, (gtpmdev.flags & (TPMIF_REQ_READY | TPMIF_CLOSED)));
+
+ /* Check if were shutting down */
+ if(gtpmdev.flags & TPMIF_CLOSED) {
+ /* if something was waiting for us to give up the queue so it can shutdown, let it finish */
+ schedule();
+ return NULL;
+ }
+
+ for(i = 0; i < gtpmdev.num_tpms; ++i) {
+ if(gtpmdev.tpmlist[i]->flags & TPMIF_REQ_READY) {
+ return get_request(gtpmdev.tpmlist[i]);
+ }
+ }
+
+ TPMBACK_ERR("backend request ready flag was set but no interfaces were actually ready\n");
+ return NULL;
+}
+
+tpmcmd_t* tpmback_req(domid_t domid, unsigned int handle)
+{
+ tpmif_t* tpmif;
+ tpmif = get_tpmif(domid, handle);
+ if(tpmif == NULL) {
+ return NULL;
+ }
+
+ wait_event(waitq, (tpmif->flags & (TPMIF_REQ_READY | TPMIF_CLOSED) || gtpmdev.flags & TPMIF_CLOSED));
+
+ /* Check if were shutting down */
+ if(tpmif->flags & TPMIF_CLOSED || gtpmdev.flags & TPMIF_CLOSED) {
+ /* if something was waiting for us to give up the queue so it can free this instance, let it finish */
+ schedule();
+ return NULL;
+ }
+
+ return get_request(tpmif);
+}
+
+void tpmback_resp(tpmcmd_t* tpmcmd)
+{
+ tpmif_t* tpmif;
+
+ /* Get the associated interface, if it doesnt exist then just quit */
+ tpmif = get_tpmif(tpmcmd->domid, tpmcmd->handle);
+ if(tpmif == NULL) {
+ TPMBACK_ERR("Tried to send a reponse to non existant frontend %u/%u\n", (unsigned int) tpmcmd->domid, tpmcmd->handle);
+ goto end;
+ }
+
+ if(!(tpmif->flags & TPMIF_REQ_READY)) {
+ TPMBACK_ERR("Tried to send response to a frontend that was not waiting for one %u/%u\n", (unsigned int) tpmcmd->domid, tpmcmd->handle);
+ goto end;
+ }
+
+ /* Send response to frontend */
+ send_response(tpmcmd, tpmif);
+
+end:
+ if(tpmcmd->req != NULL) {
+ free(tpmcmd->req);
+ }
+ free(tpmcmd);
+ return;
+}
+
+int tpmback_wait_for_frontend_connect(domid_t *domid, unsigned int *handle)
+{
+ tpmif_t* tpmif;
+ int flags;
+ wait_event(waitq, ((gtpmdev.num_tpms > 0) || gtpmdev.flags & TPMIF_CLOSED));
+ if(gtpmdev.flags & TPMIF_CLOSED) {
+ return -1;
+ }
+ local_irq_save(flags);
+ tpmif = gtpmdev.tpmlist[0];
+ *domid = tpmif->domid;
+ *handle = tpmif->handle;
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+int tpmback_num_frontends(void)
+{
+ return gtpmdev.num_tpms;
+}
--- /dev/null
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense. All rights reserved.
+ *
+ * This code has been derived from drivers/char/tpm_vtpm.c
+ * from the xen 2.6.18 linux kernel
+ *
+ * Copyright (C) 2006 IBM Corporation
+ *
+ * This code has also been derived from drivers/char/tpm_xen.c
+ * from the xen 2.6.18 linux kernel
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * which was itself derived from drivers/xen/netfront/netfront.c
+ * from the linux kernel
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+#include <mini-os/os.h>
+#include <mini-os/xenbus.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/events.h>
+#include <mini-os/wait.h>
+#include <mini-os/gnttab.h>
+#include <xen/io/xenbus.h>
+#include <xen/io/tpmif.h>
+#include <mini-os/tpmfront.h>
+#include <mini-os/lib.h>
+#include <fcntl.h>
+
+//#define TPMFRONT_PRINT_DEBUG
+#ifdef TPMFRONT_PRINT_DEBUG
+#define TPMFRONT_DEBUG(fmt,...) printk("Tpmfront:Debug("__FILE__":%d) " fmt, __LINE__, ##__VA_ARGS__)
+#define TPMFRONT_DEBUG_MORE(fmt,...) printk(fmt, ##__VA_ARGS__)
+#else
+#define TPMFRONT_DEBUG(fmt,...)
+#endif
+#define TPMFRONT_ERR(fmt,...) printk("Tpmfront:Error " fmt, ##__VA_ARGS__)
+#define TPMFRONT_LOG(fmt,...) printk("Tpmfront:Info " fmt, ##__VA_ARGS__)
+
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+
+void tpmfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data) {
+ struct tpmfront_dev* dev = (struct tpmfront_dev*) data;
+ tpmif_shared_page_t *shr = dev->page;
+ /*If we get a response when we didnt make a request, just ignore it */
+ if(!dev->waiting) {
+ return;
+ }
+
+ switch (shr->state) {
+ case TPMIF_STATE_FINISH: /* request was completed */
+ case TPMIF_STATE_IDLE: /* request was cancelled */
+ break;
+ default:
+ /* Spurious wakeup; do nothing, request is still pending */
+ return;
+ }
+
+ dev->waiting = 0;
+#ifdef HAVE_LIBC
+ if(dev->fd >= 0) {
+ files[dev->fd].read = 1;
+ }
+#endif
+ wake_up(&dev->waitq);
+}
+
+static int publish_xenbus(struct tpmfront_dev* dev) {
+ xenbus_transaction_t xbt;
+ int retry;
+ char* err;
+ /* Write the grant reference and event channel to xenstore */
+again:
+ if((err = xenbus_transaction_start(&xbt))) {
+ TPMFRONT_ERR("Unable to start xenbus transaction, error was %s\n", err);
+ free(err);
+ return -1;
+ }
+
+ if((err = xenbus_printf(xbt, dev->nodename, "ring-ref", "%u", (unsigned int) dev->ring_ref))) {
+ TPMFRONT_ERR("Unable to write %s/ring-ref, error was %s\n", dev->nodename, err);
+ free(err);
+ goto abort_transaction;
+ }
+
+ if((err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", (unsigned int) dev->evtchn))) {
+ TPMFRONT_ERR("Unable to write %s/event-channel, error was %s\n", dev->nodename, err);
+ free(err);
+ goto abort_transaction;
+ }
+
+ if((err = xenbus_transaction_end(xbt, 0, &retry))) {
+ TPMFRONT_ERR("Unable to complete xenbus transaction, error was %s\n", err);
+ free(err);
+ return -1;
+ }
+ if(retry) {
+ goto again;
+ }
+
+ return 0;
+abort_transaction:
+ if((err = xenbus_transaction_end(xbt, 1, &retry))) {
+ free(err);
+ }
+ return -1;
+}
+
+static int wait_for_backend_connect(xenbus_event_queue* events, char* path)
+{
+ int state;
+
+ TPMFRONT_LOG("Waiting for backend connection..\n");
+ /* Wait for the backend to connect */
+ while(1) {
+ state = xenbus_read_integer(path);
+ if ( state < 0)
+ state = XenbusStateUnknown;
+ switch(state) {
+ /* Bad states, we quit with error */
+ case XenbusStateUnknown:
+ case XenbusStateClosing:
+ case XenbusStateClosed:
+ TPMFRONT_ERR("Unable to connect to backend\n");
+ return -1;
+ /* If backend is connected then break out of loop */
+ case XenbusStateConnected:
+ TPMFRONT_LOG("Backend Connected\n");
+ return 0;
+ default:
+ xenbus_wait_for_watch(events);
+ }
+ }
+
+}
+
+static int wait_for_backend_closed(xenbus_event_queue* events, char* path)
+{
+ int state;
+
+ TPMFRONT_LOG("Waiting for backend to close..\n");
+ while(1) {
+ state = xenbus_read_integer(path);
+ if ( state < 0)
+ state = XenbusStateUnknown;
+ switch(state) {
+ case XenbusStateUnknown:
+ TPMFRONT_ERR("Backend Unknown state, forcing shutdown\n");
+ return -1;
+ case XenbusStateClosed:
+ TPMFRONT_LOG("Backend Closed\n");
+ return 0;
+ case XenbusStateInitWait:
+ TPMFRONT_LOG("Backend Closed (waiting for reconnect)\n");
+ return 0;
+ default:
+ xenbus_wait_for_watch(events);
+ }
+ }
+
+}
+
+static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState state) {
+ char* err;
+ int ret = 0;
+ xenbus_event_queue events = NULL;
+ char path[512];
+
+ snprintf(path, 512, "%s/state", dev->bepath);
+ /*Setup the watch to wait for the backend */
+ if((err = xenbus_watch_path_token(XBT_NIL, path, path, &events))) {
+ TPMFRONT_ERR("Could not set a watch on %s, error was %s\n", path, err);
+ free(err);
+ return -1;
+ }
+
+ /* Do the actual wait loop now */
+ switch(state) {
+ case XenbusStateConnected:
+ ret = wait_for_backend_connect(&events, path);
+ break;
+ case XenbusStateClosed:
+ ret = wait_for_backend_closed(&events, path);
+ break;
+ default:
+ TPMFRONT_ERR("Bad wait state %d, ignoring\n", state);
+ }
+
+ if((err = xenbus_unwatch_path_token(XBT_NIL, path, path))) {
+ TPMFRONT_ERR("Unable to unwatch %s, error was %s, ignoring..\n", path, err);
+ free(err);
+ }
+ return ret;
+}
+
+static int tpmfront_connect(struct tpmfront_dev* dev)
+{
+ char* err;
+ /* Create shared page */
+ dev->page = (tpmif_shared_page_t *)alloc_page();
+ if(dev->page == NULL) {
+ TPMFRONT_ERR("Unable to allocate page for shared memory\n");
+ goto error;
+ }
+ memset(dev->page, 0, PAGE_SIZE);
+ dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->page), 0);
+ TPMFRONT_DEBUG("grant ref is %lu\n", (unsigned long) dev->ring_ref);
+
+ /*Create event channel */
+ if(evtchn_alloc_unbound(dev->bedomid, tpmfront_handler, dev, &dev->evtchn)) {
+ TPMFRONT_ERR("Unable to allocate event channel\n");
+ goto error_postmap;
+ }
+ unmask_evtchn(dev->evtchn);
+ TPMFRONT_DEBUG("event channel is %lu\n", (unsigned long) dev->evtchn);
+
+ /* Write the entries to xenstore */
+ if(publish_xenbus(dev)) {
+ goto error_postevtchn;
+ }
+
+ /* Change state to connected */
+ dev->state = XenbusStateConnected;
+
+ /* Tell the backend that we are ready */
+ if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", dev->state))) {
+ TPMFRONT_ERR("Unable to write to xenstore %s/state, value=%u", dev->nodename, XenbusStateConnected);
+ free(err);
+ goto error;
+ }
+
+ return 0;
+error_postevtchn:
+ mask_evtchn(dev->evtchn);
+ unbind_evtchn(dev->evtchn);
+error_postmap:
+ gnttab_end_access(dev->ring_ref);
+ free_page(dev->page);
+error:
+ return -1;
+}
+
+struct tpmfront_dev* init_tpmfront(const char* _nodename)
+{
+ struct tpmfront_dev* dev;
+ const char* nodename;
+ char path[512];
+ char* value, *err;
+ unsigned long long ival;
+
+ printk("============= Init TPM Front ================\n");
+
+ dev = malloc(sizeof(struct tpmfront_dev));
+ memset(dev, 0, sizeof(struct tpmfront_dev));
+
+#ifdef HAVE_LIBC
+ dev->fd = -1;
+#endif
+
+ nodename = _nodename ? _nodename : "device/vtpm/0";
+ dev->nodename = strdup(nodename);
+
+ init_waitqueue_head(&dev->waitq);
+
+ /* Get backend domid */
+ snprintf(path, 512, "%s/backend-id", dev->nodename);
+ if((err = xenbus_read(XBT_NIL, path, &value))) {
+ TPMFRONT_ERR("Unable to read %s during tpmfront initialization! error = %s\n", path, err);
+ free(err);
+ goto error;
+ }
+ if(sscanf(value, "%llu", &ival) != 1) {
+ TPMFRONT_ERR("%s has non-integer value (%s)\n", path, value);
+ free(value);
+ goto error;
+ }
+ free(value);
+ dev->bedomid = ival;
+
+ /* Get backend xenstore path */
+ snprintf(path, 512, "%s/backend", dev->nodename);
+ if((err = xenbus_read(XBT_NIL, path, &dev->bepath))) {
+ TPMFRONT_ERR("Unable to read %s during tpmfront initialization! error = %s\n", path, err);
+ free(err);
+ goto error;
+ }
+
+ /* Publish protocol v2 feature */
+ snprintf(path, 512, "%s/feature-protocol-v2", dev->nodename);
+ if ((err = xenbus_write(XBT_NIL, path, "1")))
+ {
+ TPMFRONT_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
+ free(err);
+ goto error;
+ }
+
+ /* Create and publish grant reference and event channel */
+ if (tpmfront_connect(dev)) {
+ goto error;
+ }
+
+ /* Wait for backend to connect */
+ if( wait_for_backend_state_changed(dev, XenbusStateConnected)) {
+ goto error;
+ }
+
+ /* Ensure backend is also using protocol v2 */
+ snprintf(path, 512, "%s/feature-protocol-v2", dev->bepath);
+ if((err = xenbus_read(XBT_NIL, path, &value))) {
+ TPMFRONT_ERR("Unable to read %s during tpmfront initialization! error = %s\n", path, err);
+ free(err);
+ goto error;
+ }
+ if(strcmp(value, "1")) {
+ TPMFRONT_ERR("%s has an invalid value (%s)\n", path, value);
+ free(value);
+ goto error;
+ }
+ free(value);
+
+ TPMFRONT_LOG("Initialization Completed successfully\n");
+
+ return dev;
+
+error:
+ shutdown_tpmfront(dev);
+ return NULL;
+}
+void shutdown_tpmfront(struct tpmfront_dev* dev)
+{
+ char* err;
+ char path[512];
+ if(dev == NULL) {
+ return;
+ }
+ TPMFRONT_LOG("Shutting down tpmfront\n");
+ /* disconnect */
+ if(dev->state == XenbusStateConnected) {
+ /* Tell backend we are closing */
+ dev->state = XenbusStateClosing;
+ if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", (unsigned int) dev->state))) {
+ TPMFRONT_ERR("Unable to write to %s, error was %s", dev->nodename, err);
+ free(err);
+ }
+
+ /* Clean up xenstore entries */
+ snprintf(path, 512, "%s/event-channel", dev->nodename);
+ if((err = xenbus_rm(XBT_NIL, path))) {
+ free(err);
+ }
+ snprintf(path, 512, "%s/ring-ref", dev->nodename);
+ if((err = xenbus_rm(XBT_NIL, path))) {
+ free(err);
+ }
+
+ /* Tell backend we are closed */
+ dev->state = XenbusStateClosed;
+ if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", (unsigned int) dev->state))) {
+ TPMFRONT_ERR("Unable to write to %s, error was %s", dev->nodename, err);
+ free(err);
+ }
+
+ /* Wait for the backend to close and unmap shared pages, ignore any errors */
+ wait_for_backend_state_changed(dev, XenbusStateClosed);
+
+ /* Prepare for a later reopen (possibly by a kexec'd kernel) */
+ dev->state = XenbusStateInitialising;
+ if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", (unsigned int) dev->state))) {
+ TPMFRONT_ERR("Unable to write to %s, error was %s", dev->nodename, err);
+ free(err);
+ }
+
+ /* Close event channel and unmap shared page */
+ mask_evtchn(dev->evtchn);
+ unbind_evtchn(dev->evtchn);
+ gnttab_end_access(dev->ring_ref);
+
+ free_page(dev->page);
+ }
+
+ /* Cleanup memory usage */
+ if(dev->respbuf) {
+ free(dev->respbuf);
+ }
+ if(dev->bepath) {
+ free(dev->bepath);
+ }
+ if(dev->nodename) {
+ free(dev->nodename);
+ }
+ free(dev);
+}
+
+int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
+{
+ unsigned int offset;
+ tpmif_shared_page_t *shr = NULL;
+#ifdef TPMFRONT_PRINT_DEBUG
+ int i;
+#endif
+ /* Error Checking */
+ if(dev == NULL || dev->state != XenbusStateConnected) {
+ TPMFRONT_ERR("Tried to send message through disconnected frontend\n");
+ return -1;
+ }
+ shr = dev->page;
+
+#ifdef TPMFRONT_PRINT_DEBUG
+ TPMFRONT_DEBUG("Sending Msg to backend size=%u", (unsigned int) length);
+ for(i = 0; i < length; ++i) {
+ if(!(i % 30)) {
+ TPMFRONT_DEBUG_MORE("\n");
+ }
+ TPMFRONT_DEBUG_MORE("%02X ", msg[i]);
+ }
+ TPMFRONT_DEBUG_MORE("\n");
+#endif
+
+ /* Copy to shared pages now */
+ offset = sizeof(*shr);
+ if (length + offset > PAGE_SIZE) {
+ TPMFRONT_ERR("Message too long for shared page\n");
+ return -1;
+ }
+ memcpy(offset + (uint8_t*)shr, msg, length);
+ shr->length = length;
+ barrier();
+ shr->state = TPMIF_STATE_SUBMIT;
+
+ dev->waiting = 1;
+ dev->resplen = 0;
+#ifdef HAVE_LIBC
+ if(dev->fd >= 0) {
+ files[dev->fd].read = 0;
+ files[dev->fd].tpmfront.respgot = 0;
+ files[dev->fd].tpmfront.offset = 0;
+ }
+#endif
+ wmb();
+ notify_remote_via_evtchn(dev->evtchn);
+ return 0;
+}
+int tpmfront_recv(struct tpmfront_dev* dev, uint8_t** msg, size_t *length)
+{
+ unsigned int offset;
+ tpmif_shared_page_t *shr = NULL;
+#ifdef TPMFRONT_PRINT_DEBUG
+int i;
+#endif
+ if(dev == NULL || dev->state != XenbusStateConnected) {
+ TPMFRONT_ERR("Tried to receive message from disconnected frontend\n");
+ return -1;
+ }
+ /*Wait for the response */
+ wait_event(dev->waitq, (!dev->waiting));
+ shr = dev->page;
+
+ /* Initialize */
+ *msg = NULL;
+ *length = 0;
+ offset = sizeof(*shr);
+
+ if (shr->state != TPMIF_STATE_FINISH)
+ goto quit;
+
+ *length = shr->length;
+
+ if (*length + offset > PAGE_SIZE) {
+ TPMFRONT_ERR("Reply too long for shared page\n");
+ return -1;
+ }
+
+ /* Alloc the buffer */
+ if(dev->respbuf) {
+ free(dev->respbuf);
+ }
+ *msg = dev->respbuf = malloc(*length);
+ dev->resplen = *length;
+
+ /* Copy the bits */
+ memcpy(*msg, offset + (uint8_t*)shr, *length);
+
+#ifdef TPMFRONT_PRINT_DEBUG
+ TPMFRONT_DEBUG("Received response from backend size=%u", (unsigned int) *length);
+ for(i = 0; i < *length; ++i) {
+ if(!(i % 30)) {
+ TPMFRONT_DEBUG_MORE("\n");
+ }
+ TPMFRONT_DEBUG_MORE("%02X ", (*msg)[i]);
+ }
+ TPMFRONT_DEBUG_MORE("\n");
+#endif
+#ifdef HAVE_LIBC
+ if(dev->fd >= 0) {
+ files[dev->fd].tpmfront.respgot = 1;
+ }
+#endif
+quit:
+ return 0;
+}
+
+int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen)
+{
+ int rc;
+ if((rc = tpmfront_send(dev, req, reqlen))) {
+ return rc;
+ }
+ if((rc = tpmfront_recv(dev, resp, resplen))) {
+ return rc;
+ }
+
+ return 0;
+}
+
+int tpmfront_set_locality(struct tpmfront_dev* dev, int locality)
+{
+ if (!dev || !dev->page)
+ return -1;
+ dev->page->locality = locality;
+ return 0;
+}
+
+#ifdef HAVE_LIBC
+#include <errno.h>
+int tpmfront_open(struct tpmfront_dev* dev)
+{
+ /* Silently prevent multiple opens */
+ if(dev->fd != -1) {
+ return dev->fd;
+ }
+
+ dev->fd = alloc_fd(FTYPE_TPMFRONT);
+ printk("tpmfront_open(%s) -> %d\n", dev->nodename, dev->fd);
+ files[dev->fd].tpmfront.dev = dev;
+ files[dev->fd].tpmfront.offset = 0;
+ files[dev->fd].tpmfront.respgot = 0;
+ return dev->fd;
+}
+
+int tpmfront_posix_write(int fd, const uint8_t* buf, size_t count)
+{
+ int rc;
+ struct tpmfront_dev* dev;
+ dev = files[fd].tpmfront.dev;
+
+ if(count == 0) {
+ return 0;
+ }
+
+ /* Return an error if we are already processing a command */
+ if(dev->waiting) {
+ errno = EINPROGRESS;
+ return -1;
+ }
+ /* Send the command now */
+ if((rc = tpmfront_send(dev, buf, count)) != 0) {
+ errno = EIO;
+ return -1;
+ }
+ return count;
+}
+
+int tpmfront_posix_read(int fd, uint8_t* buf, size_t count)
+{
+ int rc;
+ uint8_t* dummybuf;
+ size_t dummysz;
+ struct tpmfront_dev* dev;
+
+ dev = files[fd].tpmfront.dev;
+
+ if(count == 0) {
+ return 0;
+ }
+
+ /* get the response if we haven't already */
+ if(files[dev->fd].tpmfront.respgot == 0) {
+ if ((rc = tpmfront_recv(dev, &dummybuf, &dummysz)) != 0) {
+ errno = EIO;
+ return -1;
+ }
+ }
+
+ /* handle EOF case */
+ if(files[dev->fd].tpmfront.offset >= dev->resplen) {
+ return 0;
+ }
+
+ /* Compute the number of bytes and do the copy operation */
+ if((rc = min(count, dev->resplen - files[dev->fd].tpmfront.offset)) != 0) {
+ memcpy(buf, dev->respbuf + files[dev->fd].tpmfront.offset, rc);
+ files[dev->fd].tpmfront.offset += rc;
+ }
+
+ return rc;
+}
+
+int tpmfront_posix_fstat(int fd, struct stat* buf)
+{
+ uint8_t* dummybuf;
+ size_t dummysz;
+ int rc;
+ struct tpmfront_dev* dev = files[fd].tpmfront.dev;
+
+ /* If we have a response waiting, then read it now from the backend
+ * so we can get its length*/
+ if(dev->waiting || (files[dev->fd].read == 1 && !files[dev->fd].tpmfront.respgot)) {
+ if ((rc = tpmfront_recv(dev, &dummybuf, &dummysz)) != 0) {
+ errno = EIO;
+ return -1;
+ }
+ }
+
+ buf->st_mode = O_RDWR;
+ buf->st_uid = 0;
+ buf->st_gid = 0;
+ buf->st_size = dev->resplen;
+ buf->st_atime = buf->st_mtime = buf->st_ctime = time(NULL);
+
+ return 0;
+}
+
+
+#endif
--- /dev/null
+/*
+ ****************************************************************************
+ * (C) 2006 - Cambridge University
+ ****************************************************************************
+ *
+ * File: xenbus.c
+ * Author: Steven Smith (sos22@cam.ac.uk)
+ * Changes: Grzegorz Milos (gm281@cam.ac.uk)
+ * Changes: John D. Ramsdell
+ *
+ * Date: Jun 2006, chages Aug 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: Minimal implementation of xenbus
+ *
+ ****************************************************************************
+ **/
+#include <inttypes.h>
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <mini-os/traps.h>
+#include <mini-os/lib.h>
+#include <mini-os/xenbus.h>
+#include <mini-os/events.h>
+#include <mini-os/errno.h>
+#include <mini-os/sched.h>
+#include <mini-os/wait.h>
+#include <xen/io/xs_wire.h>
+#include <mini-os/spinlock.h>
+#include <mini-os/xmalloc.h>
+
+#define min(x,y) ({ \
+ typeof(x) tmpx = (x); \
+ typeof(y) tmpy = (y); \
+ tmpx < tmpy ? tmpx : tmpy; \
+ })
+
+#ifdef XENBUS_DEBUG
+#define DEBUG(_f, _a...) \
+ printk("MINI_OS(file=xenbus.c, line=%d) " _f , __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...) ((void)0)
+#endif
+
+static struct xenstore_domain_interface *xenstore_buf;
+static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
+DECLARE_WAIT_QUEUE_HEAD(xenbus_watch_queue);
+
+xenbus_event_queue xenbus_events;
+static struct watch {
+ char *token;
+ xenbus_event_queue *events;
+ struct watch *next;
+} *watches;
+struct xenbus_req_info
+{
+ int in_use:1;
+ struct wait_queue_head waitq;
+ void *reply;
+};
+
+#define NR_REQS 32
+static struct xenbus_req_info req_info[NR_REQS];
+
+static void memcpy_from_ring(const void *Ring,
+ void *Dest,
+ int off,
+ int len)
+{
+ int c1, c2;
+ const char *ring = Ring;
+ char *dest = Dest;
+ c1 = min(len, XENSTORE_RING_SIZE - off);
+ c2 = len - c1;
+ memcpy(dest, ring + off, c1);
+ memcpy(dest + c1, ring, c2);
+}
+
+char **xenbus_wait_for_watch_return(xenbus_event_queue *queue)
+{
+ struct xenbus_event *event;
+ DEFINE_WAIT(w);
+ if (!queue)
+ queue = &xenbus_events;
+ while (!(event = *queue)) {
+ add_waiter(w, xenbus_watch_queue);
+ schedule();
+ }
+ remove_waiter(w, xenbus_watch_queue);
+ *queue = event->next;
+ return &event->path;
+}
+
+void xenbus_wait_for_watch(xenbus_event_queue *queue)
+{
+ char **ret;
+ if (!queue)
+ queue = &xenbus_events;
+ ret = xenbus_wait_for_watch_return(queue);
+ if (ret)
+ free(ret);
+ else
+ printk("unexpected path returned by watch\n");
+}
+
+char* xenbus_wait_for_value(const char* path, const char* value, xenbus_event_queue *queue)
+{
+ if (!queue)
+ queue = &xenbus_events;
+ for(;;)
+ {
+ char *res, *msg;
+ int r;
+
+ msg = xenbus_read(XBT_NIL, path, &res);
+ if(msg) return msg;
+
+ r = strcmp(value,res);
+ free(res);
+
+ if(r==0) break;
+ else xenbus_wait_for_watch(queue);
+ }
+ return NULL;
+}
+
+char *xenbus_switch_state(xenbus_transaction_t xbt, const char* path, XenbusState state)
+{
+ char *current_state;
+ char *msg = NULL;
+ char *msg2 = NULL;
+ char value[2];
+ XenbusState rs;
+ int xbt_flag = 0;
+ int retry = 0;
+
+ do {
+ if (xbt == XBT_NIL) {
+ msg = xenbus_transaction_start(&xbt);
+ if (msg) goto exit;
+ xbt_flag = 1;
+ }
+
+ msg = xenbus_read(xbt, path, ¤t_state);
+ if (msg) goto exit;
+
+ rs = (XenbusState) (current_state[0] - '0');
+ free(current_state);
+ if (rs == state) {
+ msg = NULL;
+ goto exit;
+ }
+
+ snprintf(value, 2, "%d", state);
+ msg = xenbus_write(xbt, path, value);
+
+exit:
+ if (xbt_flag) {
+ msg2 = xenbus_transaction_end(xbt, 0, &retry);
+ xbt = XBT_NIL;
+ }
+ if (msg == NULL && msg2 != NULL)
+ msg = msg2;
+ } while (retry);
+
+ return msg;
+}
+
+char *xenbus_wait_for_state_change(const char* path, XenbusState *state, xenbus_event_queue *queue)
+{
+ if (!queue)
+ queue = &xenbus_events;
+ for(;;)
+ {
+ char *res, *msg;
+ XenbusState rs;
+
+ msg = xenbus_read(XBT_NIL, path, &res);
+ if(msg) return msg;
+
+ rs = (XenbusState) (res[0] - 48);
+ free(res);
+
+ if (rs == *state)
+ xenbus_wait_for_watch(queue);
+ else {
+ *state = rs;
+ break;
+ }
+ }
+ return NULL;
+}
+
+
+static void xenbus_thread_func(void *ign)
+{
+ struct xsd_sockmsg msg;
+ unsigned prod = xenstore_buf->rsp_prod;
+
+ for (;;)
+ {
+ wait_event(xb_waitq, prod != xenstore_buf->rsp_prod);
+ while (1)
+ {
+ prod = xenstore_buf->rsp_prod;
+ DEBUG("Rsp_cons %d, rsp_prod %d.\n", xenstore_buf->rsp_cons,
+ xenstore_buf->rsp_prod);
+ if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg))
+ break;
+ rmb();
+ memcpy_from_ring(xenstore_buf->rsp,
+ &msg,
+ MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
+ sizeof(msg));
+ DEBUG("Msg len %d, %d avail, id %d.\n",
+ msg.len + sizeof(msg),
+ xenstore_buf->rsp_prod - xenstore_buf->rsp_cons,
+ msg.req_id);
+ if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons <
+ sizeof(msg) + msg.len)
+ break;
+
+ DEBUG("Message is good.\n");
+
+ if(msg.type == XS_WATCH_EVENT)
+ {
+ struct xenbus_event *event = malloc(sizeof(*event) + msg.len);
+ xenbus_event_queue *events = NULL;
+ char *data = (char*)event + sizeof(*event);
+ struct watch *watch;
+
+ memcpy_from_ring(xenstore_buf->rsp,
+ data,
+ MASK_XENSTORE_IDX(xenstore_buf->rsp_cons + sizeof(msg)),
+ msg.len);
+
+ event->path = data;
+ event->token = event->path + strlen(event->path) + 1;
+
+ xenstore_buf->rsp_cons += msg.len + sizeof(msg);
+
+ for (watch = watches; watch; watch = watch->next)
+ if (!strcmp(watch->token, event->token)) {
+ events = watch->events;
+ break;
+ }
+
+ if (events) {
+ event->next = *events;
+ *events = event;
+ wake_up(&xenbus_watch_queue);
+ } else {
+ printk("unexpected watch token %s\n", event->token);
+ free(event);
+ }
+ }
+
+ else
+ {
+ req_info[msg.req_id].reply = malloc(sizeof(msg) + msg.len);
+ memcpy_from_ring(xenstore_buf->rsp,
+ req_info[msg.req_id].reply,
+ MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
+ msg.len + sizeof(msg));
+ xenstore_buf->rsp_cons += msg.len + sizeof(msg);
+ wake_up(&req_info[msg.req_id].waitq);
+ }
+ }
+ }
+}
+
+static void xenbus_evtchn_handler(evtchn_port_t port, struct pt_regs *regs,
+ void *ign)
+{
+ wake_up(&xb_waitq);
+}
+
+static int nr_live_reqs;
+static DEFINE_SPINLOCK(req_lock);
+static DECLARE_WAIT_QUEUE_HEAD(req_wq);
+
+/* Release a xenbus identifier */
+static void release_xenbus_id(int id)
+{
+ BUG_ON(!req_info[id].in_use);
+ spin_lock(&req_lock);
+ req_info[id].in_use = 0;
+ nr_live_reqs--;
+ req_info[id].in_use = 0;
+ if (nr_live_reqs == NR_REQS - 1)
+ wake_up(&req_wq);
+ spin_unlock(&req_lock);
+}
+
+/* Allocate an identifier for a xenbus request. Blocks if none are
+ available. */
+static int allocate_xenbus_id(void)
+{
+ static int probe;
+ int o_probe;
+
+ while (1)
+ {
+ spin_lock(&req_lock);
+ if (nr_live_reqs < NR_REQS)
+ break;
+ spin_unlock(&req_lock);
+ wait_event(req_wq, (nr_live_reqs < NR_REQS));
+ }
+
+ o_probe = probe;
+ for (;;)
+ {
+ if (!req_info[o_probe].in_use)
+ break;
+ o_probe = (o_probe + 1) % NR_REQS;
+ BUG_ON(o_probe == probe);
+ }
+ nr_live_reqs++;
+ req_info[o_probe].in_use = 1;
+ probe = (o_probe + 1) % NR_REQS;
+ spin_unlock(&req_lock);
+ init_waitqueue_head(&req_info[o_probe].waitq);
+
+ return o_probe;
+}
+
+/* Initialise xenbus. */
+void init_xenbus(void)
+{
+ int err;
+ DEBUG("init_xenbus called.\n");
+ xenstore_buf = mfn_to_virt(start_info.store_mfn);
+ create_thread("xenstore", xenbus_thread_func, NULL);
+ DEBUG("buf at %p.\n", xenstore_buf);
+ err = bind_evtchn(start_info.store_evtchn,
+ xenbus_evtchn_handler,
+ NULL);
+ unmask_evtchn(start_info.store_evtchn);
+ printk("xenbus initialised on irq %d mfn %#lx\n",
+ err, start_info.store_mfn);
+}
+
+void fini_xenbus(void)
+{
+}
+
+/* Send data to xenbus. This can block. All of the requests are seen
+ by xenbus as if sent atomically. The header is added
+ automatically, using type %type, req_id %req_id, and trans_id
+ %trans_id. */
+static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
+ const struct write_req *req, int nr_reqs)
+{
+ XENSTORE_RING_IDX prod;
+ int r;
+ int len = 0;
+ const struct write_req *cur_req;
+ int req_off;
+ int total_off;
+ int this_chunk;
+ struct xsd_sockmsg m = {.type = type, .req_id = req_id,
+ .tx_id = trans_id };
+ struct write_req header_req = { &m, sizeof(m) };
+
+ for (r = 0; r < nr_reqs; r++)
+ len += req[r].len;
+ m.len = len;
+ len += sizeof(m);
+
+ cur_req = &header_req;
+
+ BUG_ON(len > XENSTORE_RING_SIZE);
+ /* Wait for the ring to drain to the point where we can send the
+ message. */
+ prod = xenstore_buf->req_prod;
+ if (prod + len - xenstore_buf->req_cons > XENSTORE_RING_SIZE)
+ {
+ /* Wait for there to be space on the ring */
+ DEBUG("prod %d, len %d, cons %d, size %d; waiting.\n",
+ prod, len, xenstore_buf->req_cons, XENSTORE_RING_SIZE);
+ wait_event(xb_waitq,
+ xenstore_buf->req_prod + len - xenstore_buf->req_cons <=
+ XENSTORE_RING_SIZE);
+ DEBUG("Back from wait.\n");
+ prod = xenstore_buf->req_prod;
+ }
+
+ /* We're now guaranteed to be able to send the message without
+ overflowing the ring. Do so. */
+ total_off = 0;
+ req_off = 0;
+ while (total_off < len)
+ {
+ this_chunk = min(cur_req->len - req_off,
+ XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
+ memcpy((char *)xenstore_buf->req + MASK_XENSTORE_IDX(prod),
+ (char *)cur_req->data + req_off, this_chunk);
+ prod += this_chunk;
+ req_off += this_chunk;
+ total_off += this_chunk;
+ if (req_off == cur_req->len)
+ {
+ req_off = 0;
+ if (cur_req == &header_req)
+ cur_req = req;
+ else
+ cur_req++;
+ }
+ }
+
+ DEBUG("Complete main loop of xb_write.\n");
+ BUG_ON(req_off != 0);
+ BUG_ON(total_off != len);
+ BUG_ON(prod > xenstore_buf->req_cons + XENSTORE_RING_SIZE);
+
+ /* Remote must see entire message before updating indexes */
+ wmb();
+
+ xenstore_buf->req_prod += len;
+
+ /* Send evtchn to notify remote */
+ notify_remote_via_evtchn(start_info.store_evtchn);
+}
+
+/* Send a mesasge to xenbus, in the same fashion as xb_write, and
+ block waiting for a reply. The reply is malloced and should be
+ freed by the caller. */
+struct xsd_sockmsg *
+xenbus_msg_reply(int type,
+ xenbus_transaction_t trans,
+ struct write_req *io,
+ int nr_reqs)
+{
+ int id;
+ DEFINE_WAIT(w);
+ struct xsd_sockmsg *rep;
+
+ id = allocate_xenbus_id();
+ add_waiter(w, req_info[id].waitq);
+
+ xb_write(type, id, trans, io, nr_reqs);
+
+ schedule();
+ remove_waiter(w, req_info[id].waitq);
+ wake(current);
+
+ rep = req_info[id].reply;
+ BUG_ON(rep->req_id != id);
+ release_xenbus_id(id);
+ return rep;
+}
+
+static char *errmsg(struct xsd_sockmsg *rep)
+{
+ char *res;
+ if (!rep) {
+ char msg[] = "No reply";
+ size_t len = strlen(msg) + 1;
+ return memcpy(malloc(len), msg, len);
+ }
+ if (rep->type != XS_ERROR)
+ return NULL;
+ res = malloc(rep->len + 1);
+ memcpy(res, rep + 1, rep->len);
+ res[rep->len] = 0;
+ free(rep);
+ return res;
+}
+
+/* Send a debug message to xenbus. Can block. */
+static void xenbus_debug_msg(const char *msg)
+{
+ int len = strlen(msg);
+ struct write_req req[] = {
+ { "print", sizeof("print") },
+ { msg, len },
+ { "", 1 }};
+ struct xsd_sockmsg *reply;
+
+ reply = xenbus_msg_reply(XS_DEBUG, 0, req, ARRAY_SIZE(req));
+ printk("Got a reply, type %d, id %d, len %d.\n",
+ reply->type, reply->req_id, reply->len);
+}
+
+/* List the contents of a directory. Returns a malloc()ed array of
+ pointers to malloc()ed strings. The array is NULL terminated. May
+ block. */
+char *xenbus_ls(xenbus_transaction_t xbt, const char *pre, char ***contents)
+{
+ struct xsd_sockmsg *reply, *repmsg;
+ struct write_req req[] = { { pre, strlen(pre)+1 } };
+ int nr_elems, x, i;
+ char **res, *msg;
+
+ repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
+ msg = errmsg(repmsg);
+ if (msg) {
+ *contents = NULL;
+ return msg;
+ }
+ reply = repmsg + 1;
+ for (x = nr_elems = 0; x < repmsg->len; x++)
+ nr_elems += (((char *)reply)[x] == 0);
+ res = malloc(sizeof(res[0]) * (nr_elems + 1));
+ for (x = i = 0; i < nr_elems; i++) {
+ int l = strlen((char *)reply + x);
+ res[i] = malloc(l + 1);
+ memcpy(res[i], (char *)reply + x, l + 1);
+ x += l + 1;
+ }
+ res[i] = NULL;
+ free(repmsg);
+ *contents = res;
+ return NULL;
+}
+
+char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value)
+{
+ struct write_req req[] = { {path, strlen(path) + 1} };
+ struct xsd_sockmsg *rep;
+ char *res, *msg;
+ rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req));
+ msg = errmsg(rep);
+ if (msg) {
+ *value = NULL;
+ return msg;
+ }
+ res = malloc(rep->len + 1);
+ memcpy(res, rep + 1, rep->len);
+ res[rep->len] = 0;
+ free(rep);
+ *value = res;
+ return NULL;
+}
+
+char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value)
+{
+ struct write_req req[] = {
+ {path, strlen(path) + 1},
+ {value, strlen(value)},
+ };
+ struct xsd_sockmsg *rep;
+ char *msg;
+ rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
+ msg = errmsg(rep);
+ if (msg) return msg;
+ free(rep);
+ return NULL;
+}
+
+char* xenbus_watch_path_token( xenbus_transaction_t xbt, const char *path, const char *token, xenbus_event_queue *events)
+{
+ struct xsd_sockmsg *rep;
+
+ struct write_req req[] = {
+ {path, strlen(path) + 1},
+ {token, strlen(token) + 1},
+ };
+
+ struct watch *watch = malloc(sizeof(*watch));
+
+ char *msg;
+
+ if (!events)
+ events = &xenbus_events;
+
+ watch->token = strdup(token);
+ watch->events = events;
+ watch->next = watches;
+ watches = watch;
+
+ rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req));
+
+ msg = errmsg(rep);
+ if (msg) return msg;
+ free(rep);
+
+ return NULL;
+}
+
+char* xenbus_unwatch_path_token( xenbus_transaction_t xbt, const char *path, const char *token)
+{
+ struct xsd_sockmsg *rep;
+
+ struct write_req req[] = {
+ {path, strlen(path) + 1},
+ {token, strlen(token) + 1},
+ };
+
+ struct watch *watch, **prev;
+
+ char *msg;
+
+ rep = xenbus_msg_reply(XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
+
+ msg = errmsg(rep);
+ if (msg) return msg;
+ free(rep);
+
+ for (prev = &watches, watch = *prev; watch; prev = &watch->next, watch = *prev)
+ if (!strcmp(watch->token, token)) {
+ free(watch->token);
+ *prev = watch->next;
+ free(watch);
+ break;
+ }
+
+ return NULL;
+}
+
+char *xenbus_rm(xenbus_transaction_t xbt, const char *path)
+{
+ struct write_req req[] = { {path, strlen(path) + 1} };
+ struct xsd_sockmsg *rep;
+ char *msg;
+ rep = xenbus_msg_reply(XS_RM, xbt, req, ARRAY_SIZE(req));
+ msg = errmsg(rep);
+ if (msg)
+ return msg;
+ free(rep);
+ return NULL;
+}
+
+char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value)
+{
+ struct write_req req[] = { {path, strlen(path) + 1} };
+ struct xsd_sockmsg *rep;
+ char *res, *msg;
+ rep = xenbus_msg_reply(XS_GET_PERMS, xbt, req, ARRAY_SIZE(req));
+ msg = errmsg(rep);
+ if (msg) {
+ *value = NULL;
+ return msg;
+ }
+ res = malloc(rep->len + 1);
+ memcpy(res, rep + 1, rep->len);
+ res[rep->len] = 0;
+ free(rep);
+ *value = res;
+ return NULL;
+}
+
+#define PERM_MAX_SIZE 32
+char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t dom, char perm)
+{
+ char value[PERM_MAX_SIZE];
+ struct write_req req[] = {
+ {path, strlen(path) + 1},
+ {value, 0},
+ };
+ struct xsd_sockmsg *rep;
+ char *msg;
+ snprintf(value, PERM_MAX_SIZE, "%c%hu", perm, dom);
+ req[1].len = strlen(value) + 1;
+ rep = xenbus_msg_reply(XS_SET_PERMS, xbt, req, ARRAY_SIZE(req));
+ msg = errmsg(rep);
+ if (msg)
+ return msg;
+ free(rep);
+ return NULL;
+}
+
+char *xenbus_transaction_start(xenbus_transaction_t *xbt)
+{
+ /* xenstored becomes angry if you send a length 0 message, so just
+ shove a nul terminator on the end */
+ struct write_req req = { "", 1};
+ struct xsd_sockmsg *rep;
+ char *err;
+
+ rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1);
+ err = errmsg(rep);
+ if (err)
+ return err;
+ sscanf((char *)(rep + 1), "%lu", xbt);
+ free(rep);
+ return NULL;
+}
+
+char *
+xenbus_transaction_end(xenbus_transaction_t t, int abort, int *retry)
+{
+ struct xsd_sockmsg *rep;
+ struct write_req req;
+ char *err;
+
+ *retry = 0;
+
+ req.data = abort ? "F" : "T";
+ req.len = 2;
+ rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1);
+ err = errmsg(rep);
+ if (err) {
+ if (!strcmp(err, "EAGAIN")) {
+ *retry = 1;
+ free(err);
+ return NULL;
+ } else {
+ return err;
+ }
+ }
+ free(rep);
+ return NULL;
+}
+
+int xenbus_read_integer(const char *path)
+{
+ char *res, *buf;
+ int t;
+
+ res = xenbus_read(XBT_NIL, path, &buf);
+ if (res) {
+ printk("Failed to read %s.\n", path);
+ free(res);
+ return -1;
+ }
+ sscanf(buf, "%d", &t);
+ free(buf);
+ return t;
+}
+
+int xenbus_read_uuid(const char* path, unsigned char uuid[16]) {
+ char * res, *buf;
+ res = xenbus_read(XBT_NIL, path, &buf);
+ if(res) {
+ printk("Failed to read %s.\n", path);
+ free(res);
+ return 0;
+ }
+ if(strlen(buf) != ((2*16)+4) /* 16 hex bytes and 4 hyphens */
+ || sscanf(buf,
+ "%2hhx%2hhx%2hhx%2hhx-"
+ "%2hhx%2hhx-"
+ "%2hhx%2hhx-"
+ "%2hhx%2hhx-"
+ "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
+ uuid, uuid + 1, uuid + 2, uuid + 3,
+ uuid + 4, uuid + 5, uuid + 6, uuid + 7,
+ uuid + 8, uuid + 9, uuid + 10, uuid + 11,
+ uuid + 12, uuid + 13, uuid + 14, uuid + 15) != 16) {
+ printk("Xenbus path %s value %s is not a uuid!\n", path, buf);
+ free(buf);
+ return 0;
+ }
+ free(buf);
+ return 1;
+}
+
+char* xenbus_printf(xenbus_transaction_t xbt,
+ const char* node, const char* path,
+ const char* fmt, ...)
+{
+#define BUFFER_SIZE 256
+ char fullpath[BUFFER_SIZE];
+ char val[BUFFER_SIZE];
+ va_list args;
+
+ BUG_ON(strlen(node) + strlen(path) + 1 >= BUFFER_SIZE);
+ sprintf(fullpath,"%s/%s", node, path);
+ va_start(args, fmt);
+ vsprintf(val, fmt, args);
+ va_end(args);
+ return xenbus_write(xbt,fullpath,val);
+}
+
+domid_t xenbus_get_self_id(void)
+{
+ char *dom_id;
+ domid_t ret;
+
+ BUG_ON(xenbus_read(XBT_NIL, "domid", &dom_id));
+ sscanf(dom_id, "%"SCNd16, &ret);
+
+ return ret;
+}
+
+static void do_ls_test(const char *pre)
+{
+ char **dirs, *msg;
+ int x;
+
+ printk("ls %s...\n", pre);
+ msg = xenbus_ls(XBT_NIL, pre, &dirs);
+ if (msg) {
+ printk("Error in xenbus ls: %s\n", msg);
+ free(msg);
+ return;
+ }
+ for (x = 0; dirs[x]; x++)
+ {
+ printk("ls %s[%d] -> %s\n", pre, x, dirs[x]);
+ free(dirs[x]);
+ }
+ free(dirs);
+}
+
+static void do_read_test(const char *path)
+{
+ char *res, *msg;
+ printk("Read %s...\n", path);
+ msg = xenbus_read(XBT_NIL, path, &res);
+ if (msg) {
+ printk("Error in xenbus read: %s\n", msg);
+ free(msg);
+ return;
+ }
+ printk("Read %s -> %s.\n", path, res);
+ free(res);
+}
+
+static void do_write_test(const char *path, const char *val)
+{
+ char *msg;
+ printk("Write %s to %s...\n", val, path);
+ msg = xenbus_write(XBT_NIL, path, val);
+ if (msg) {
+ printk("Result %s\n", msg);
+ free(msg);
+ } else {
+ printk("Success.\n");
+ }
+}
+
+static void do_rm_test(const char *path)
+{
+ char *msg;
+ printk("rm %s...\n", path);
+ msg = xenbus_rm(XBT_NIL, path);
+ if (msg) {
+ printk("Result %s\n", msg);
+ free(msg);
+ } else {
+ printk("Success.\n");
+ }
+}
+
+/* Simple testing thing */
+void test_xenbus(void)
+{
+ printk("Doing xenbus test.\n");
+ xenbus_debug_msg("Testing xenbus...\n");
+
+ printk("Doing ls test.\n");
+ do_ls_test("device");
+ do_ls_test("device/vif");
+ do_ls_test("device/vif/0");
+
+ printk("Doing read test.\n");
+ do_read_test("device/vif/0/mac");
+ do_read_test("device/vif/0/backend");
+
+ printk("Doing write test.\n");
+ do_write_test("device/vif/0/flibble", "flobble");
+ do_read_test("device/vif/0/flibble");
+ do_write_test("device/vif/0/flibble", "widget");
+ do_read_test("device/vif/0/flibble");
+
+ printk("Doing rm test.\n");
+ do_rm_test("device/vif/0/flibble");
+ do_read_test("device/vif/0/flibble");
+ printk("(Should have said ENOENT)\n");
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * End:
+ */
+++ /dev/null
-Certain files in this directory are licensed by the GNU
-General Public License version 2 (GPLv2). By default these
-files are not built and linked into MiniOs. Enabling them
-will cause the whole work to become covered by the GPLv2.
-
-The current set of GPLv2 features are:
-CONFIG_TPMFRONT
-CONFIG_TPMBACK
-CONFIG_TPM_TIS
-
-Do not use these if you do not want your MiniOS build to become
-GPL licensed!
-
-Copyright (c) 2009 Citrix Systems, Inc. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
+++ /dev/null
-#
-# Compare $(1) and $(2) and replace $(2) with $(1) if they differ
-#
-# Typically $(1) is a newly generated file and $(2) is the target file
-# being regenerated. This prevents changing the timestamp of $(2) only
-# due to being auto regenereated with the same contents.
-define move-if-changed
- if ! cmp -s $(1) $(2); then mv -f $(1) $(2); else rm -f $(1); fi
-endef
-
-# cc-option: Check if compiler supports first option, else fall back to second.
-#
-# This is complicated by the fact that unrecognised -Wno-* options:
-# (a) are ignored unless the compilation emits a warning; and
-# (b) even then produce a warning rather than an error
-# To handle this we do a test compile, passing the option-under-test, on a code
-# fragment that will always produce a warning (integer assigned to pointer).
-# We then grep for the option-under-test in the compiler's output, the presence
-# of which would indicate an "unrecognized command-line option" warning/error.
-#
-# Usage: cflags-y += $(call cc-option,$(CC),-march=winchip-c6,-march=i586)
-cc-option = $(shell if test -z "`echo 'void*p=1;' | \
- $(1) $(2) -S -o /dev/null -x c - 2>&1 | grep -- $(2) -`"; \
- then echo "$(2)"; else echo "$(3)"; fi ;)
-
-# Compatibility with Xen's stubdom build environment. If we are building
-# stubdom, some XEN_ variables are set, set MINIOS_ variables accordingly.
-#
-ifneq ($(XEN_ROOT),)
-MINI-OS_ROOT=$(XEN_ROOT)/extras/mini-os
-else
-MINI-OS_ROOT=$(TOPLEVEL_DIR)
-endif
-export MINI-OS_ROOT
-
-ifneq ($(XEN_TARGET_ARCH),)
-MINIOS_TARGET_ARCH = $(XEN_TARGET_ARCH)
-else
-MINIOS_COMPILE_ARCH ?= $(shell uname -m | sed -e s/i.86/x86_32/ \
- -e s/i86pc/x86_32/ -e s/amd64/x86_64/ \
- -e s/armv7.*/arm32/ -e s/armv8.*/arm64/ \
- -e s/aarch64/arm64/)
-
-MINIOS_TARGET_ARCH ?= $(MINIOS_COMPILE_ARCH)
-endif
-
-libc = $(stubdom)
-
-XEN_INTERFACE_VERSION := 0x00030205
-export XEN_INTERFACE_VERSION
-
-# Try to find out the architecture family TARGET_ARCH_FAM.
-# First check whether x86_... is contained (for x86_32, x86_32y, x86_64).
-# If not x86 then use $(MINIOS_TARGET_ARCH)
-ifeq ($(findstring x86_,$(MINIOS_TARGET_ARCH)),x86_)
-TARGET_ARCH_FAM = x86
-else
-TARGET_ARCH_FAM = $(MINIOS_TARGET_ARCH)
-endif
-
-# The architecture family directory below mini-os.
-TARGET_ARCH_DIR := arch/$(TARGET_ARCH_FAM)
-
-# Export these variables for possible use in architecture dependent makefiles.
-export TARGET_ARCH_DIR
-export TARGET_ARCH_FAM
-
-# This is used for architecture specific links.
-# This can be overwritten from arch specific rules.
-ARCH_LINKS =
-
-# The path pointing to the architecture specific header files.
-ARCH_INC := $(TARGET_ARCH_FAM)
-
-# For possible special header directories.
-# This can be overwritten from arch specific rules.
-EXTRA_INC = $(ARCH_INC)
-
-# Include the architecture family's special makerules.
-# This must be before include minios.mk!
-include $(MINI-OS_ROOT)/$(TARGET_ARCH_DIR)/arch.mk
-
-extra_incl := $(foreach dir,$(EXTRA_INC),-isystem $(MINI-OS_ROOT)/include/$(dir))
-
-DEF_CPPFLAGS += -isystem $(MINI-OS_ROOT)/include
-DEF_CPPFLAGS += -D__MINIOS__
-
-ifeq ($(libc),y)
-DEF_CPPFLAGS += -DHAVE_LIBC
-DEF_CPPFLAGS += -isystem $(MINI-OS_ROOT)/include/posix
-DEF_CPPFLAGS += -isystem $(XEN_ROOT)/tools/xenstore/include
-endif
-
-ifneq ($(LWIPDIR),)
-lwip=y
-DEF_CPPFLAGS += -DHAVE_LWIP
-DEF_CPPFLAGS += -isystem $(LWIPDIR)/src/include
-DEF_CPPFLAGS += -isystem $(LWIPDIR)/src/include/ipv4
-endif
+++ /dev/null
-# Common Makefile for mini-os.
-#
-# Every architecture directory below mini-os/arch has to have a
-# Makefile and a arch.mk.
-#
-
-OBJ_DIR=$(CURDIR)
-TOPLEVEL_DIR=$(CURDIR)
-
-ifeq ($(MINIOS_CONFIG),)
-include Config.mk
-else
-EXTRA_DEPS += $(MINIOS_CONFIG)
-include $(MINIOS_CONFIG)
-endif
-
-include $(MINI-OS_ROOT)/config/MiniOS.mk
-
-# Configuration defaults
-CONFIG_START_NETWORK ?= y
-CONFIG_SPARSE_BSS ?= y
-CONFIG_QEMU_XS_ARGS ?= n
-CONFIG_TEST ?= n
-CONFIG_PCIFRONT ?= n
-CONFIG_BLKFRONT ?= y
-CONFIG_TPMFRONT ?= n
-CONFIG_TPM_TIS ?= n
-CONFIG_TPMBACK ?= n
-CONFIG_NETFRONT ?= y
-CONFIG_FBFRONT ?= y
-CONFIG_KBDFRONT ?= y
-CONFIG_CONSFRONT ?= y
-CONFIG_XENBUS ?= y
-CONFIG_XC ?=y
-CONFIG_LWIP ?= $(lwip)
-
-# Export config items as compiler directives
-flags-$(CONFIG_START_NETWORK) += -DCONFIG_START_NETWORK
-flags-$(CONFIG_SPARSE_BSS) += -DCONFIG_SPARSE_BSS
-flags-$(CONFIG_QEMU_XS_ARGS) += -DCONFIG_QEMU_XS_ARGS
-flags-$(CONFIG_PCIFRONT) += -DCONFIG_PCIFRONT
-flags-$(CONFIG_BLKFRONT) += -DCONFIG_BLKFRONT
-flags-$(CONFIG_TPMFRONT) += -DCONFIG_TPMFRONT
-flags-$(CONFIG_TPM_TIS) += -DCONFIG_TPM_TIS
-flags-$(CONFIG_TPMBACK) += -DCONFIG_TPMBACK
-flags-$(CONFIG_NETFRONT) += -DCONFIG_NETFRONT
-flags-$(CONFIG_KBDFRONT) += -DCONFIG_KBDFRONT
-flags-$(CONFIG_FBFRONT) += -DCONFIG_FBFRONT
-flags-$(CONFIG_CONSFRONT) += -DCONFIG_CONSFRONT
-flags-$(CONFIG_XENBUS) += -DCONFIG_XENBUS
-
-DEF_CFLAGS += $(flags-y)
-
-# Symlinks and headers that must be created before building the C files
-GENERATED_HEADERS := include/list.h $(ARCH_LINKS) include/mini-os include/$(TARGET_ARCH_FAM)/mini-os
-
-EXTRA_DEPS += $(GENERATED_HEADERS)
-
-# Include common mini-os makerules.
-include minios.mk
-
-# Set tester flags
-# CFLAGS += -DBLKTEST_WRITE
-
-# Define some default flags for linking.
-LDLIBS :=
-APP_LDLIBS :=
-LDARCHLIB := -L$(OBJ_DIR)/$(TARGET_ARCH_DIR) -l$(ARCH_LIB_NAME)
-LDFLAGS_FINAL := -T $(TARGET_ARCH_DIR)/minios-$(MINIOS_TARGET_ARCH).lds
-
-# Prefix for global API names. All other symbols are localised before
-# linking with EXTRA_OBJS.
-GLOBAL_PREFIX := xenos_
-EXTRA_OBJS =
-
-TARGET := mini-os
-
-# Subdirectories common to mini-os
-SUBDIRS := lib xenbus console
-
-src-$(CONFIG_BLKFRONT) += blkfront.c
-src-$(CONFIG_TPMFRONT) += tpmfront.c
-src-$(CONFIG_TPM_TIS) += tpm_tis.c
-src-$(CONFIG_TPMBACK) += tpmback.c
-src-y += daytime.c
-src-y += events.c
-src-$(CONFIG_FBFRONT) += fbfront.c
-src-y += gntmap.c
-src-y += gnttab.c
-src-y += hypervisor.c
-src-y += kernel.c
-src-y += lock.c
-src-y += main.c
-src-y += mm.c
-src-$(CONFIG_NETFRONT) += netfront.c
-src-$(CONFIG_PCIFRONT) += pcifront.c
-src-y += sched.c
-src-$(CONFIG_TEST) += test.c
-
-src-y += lib/ctype.c
-src-y += lib/math.c
-src-y += lib/printf.c
-src-y += lib/stack_chk_fail.c
-src-y += lib/string.c
-src-y += lib/sys.c
-src-y += lib/xmalloc.c
-src-$(CONFIG_XENBUS) += lib/xs.c
-
-src-$(CONFIG_XENBUS) += xenbus/xenbus.c
-
-src-y += console/console.c
-src-y += console/xencons_ring.c
-src-$(CONFIG_CONSFRONT) += console/xenbus.c
-
-# The common mini-os objects to build.
-APP_OBJS :=
-OBJS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(src-y))
-
-.PHONY: default
-default: $(OBJ_DIR)/$(TARGET)
-
-# Create special architecture specific links. The function arch_links
-# has to be defined in arch.mk (see include above).
-ifneq ($(ARCH_LINKS),)
-$(ARCH_LINKS):
- $(arch_links)
-endif
-
-include/list.h: include/minios-external/bsd-sys-queue-h-seddery include/minios-external/bsd-sys-queue.h
- perl $^ --prefix=minios >$@.new
- $(call move-if-changed,$@.new,$@)
-
-# Used by stubdom's Makefile
-.PHONY: links
-links: $(GENERATED_HEADERS)
-
-include/mini-os:
- ln -sf . $@
-
-include/$(TARGET_ARCH_FAM)/mini-os:
- ln -sf . $@
-
-.PHONY: arch_lib
-arch_lib:
- $(MAKE) --directory=$(TARGET_ARCH_DIR) OBJ_DIR=$(OBJ_DIR)/$(TARGET_ARCH_DIR) || exit 1;
-
-ifeq ($(CONFIG_LWIP),y)
-# lwIP library
-LWC := $(shell find $(LWIPDIR)/src -type f -name '*.c')
-LWC := $(filter-out %6.c %ip6_addr.c %ethernetif.c, $(LWC))
-LWO := $(patsubst %.c,%.o,$(LWC))
-LWO += $(OBJ_DIR)/lwip-arch.o
-ifeq ($(CONFIG_NETFRONT),y)
-LWO += $(OBJ_DIR)/lwip-net.o
-endif
-
-$(OBJ_DIR)/lwip.a: $(LWO)
- $(RM) $@
- $(AR) cqs $@ $^
-
-OBJS += $(OBJ_DIR)/lwip.a
-endif
-
-OBJS := $(filter-out $(OBJ_DIR)/lwip%.o $(LWO), $(OBJS))
-
-ifeq ($(libc),y)
-ifeq ($(CONFIG_XC),y)
-APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxc-$(XEN_TARGET_ARCH) -whole-archive -lxenguest -lxenctrl -no-whole-archive
-endif
-APP_LDLIBS += -lpci
-APP_LDLIBS += -lz
-APP_LDLIBS += -lm
-LDLIBS += -lc
-endif
-
-ifneq ($(APP_OBJS)-$(lwip),-y)
-OBJS := $(filter-out $(OBJ_DIR)/daytime.o, $(OBJS))
-endif
-
-$(OBJ_DIR)/$(TARGET)_app.o: $(APP_OBJS) app.lds
- $(LD) -r -d $(LDFLAGS) -\( $^ -\) $(APP_LDLIBS) --undefined main -o $@
-
-ifneq ($(APP_OBJS),)
-APP_O=$(OBJ_DIR)/$(TARGET)_app.o
-endif
-
-$(OBJ_DIR)/$(TARGET): $(OBJS) $(APP_O) arch_lib
- $(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(APP_O) $(OBJS) $(LDARCHLIB) $(LDLIBS) -o $@.o
- $(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o
- $(LD) $(LDFLAGS) $(LDFLAGS_FINAL) $@.o $(EXTRA_OBJS) -o $@
- gzip -f -9 -c $@ >$@.gz
-
-.PHONY: clean arch_clean
-
-arch_clean:
- $(MAKE) --directory=$(TARGET_ARCH_DIR) OBJ_DIR=$(OBJ_DIR)/$(TARGET_ARCH_DIR) clean || exit 1;
-
-clean: arch_clean
- for dir in $(addprefix $(OBJ_DIR)/,$(SUBDIRS)); do \
- rm -f $$dir/*.o; \
- done
- rm -f include/list.h
- rm -f $(OBJ_DIR)/*.o *~ $(OBJ_DIR)/core $(OBJ_DIR)/$(TARGET).elf $(OBJ_DIR)/$(TARGET).raw $(OBJ_DIR)/$(TARGET) $(OBJ_DIR)/$(TARGET).gz
- find . $(OBJ_DIR) -type l | xargs rm -f
- $(RM) $(OBJ_DIR)/lwip.a $(LWO)
- rm -f tags TAGS
-
-
-define all_sources
- ( find . -follow -name SCCS -prune -o -name '*.[chS]' -print )
-endef
-
-.PHONY: cscope
-cscope:
- $(all_sources) > cscope.files
- cscope -k -b -q
-
-.PHONY: tags
-tags:
- $(all_sources) | xargs ctags
-
-.PHONY: TAGS
-TAGS:
- $(all_sources) | xargs etags
+++ /dev/null
- Minimal OS
- ----------
-
-This shows some of the stuff that any guest OS will have to set up.
-
-This includes:
-
- * installing a virtual exception table
- * handling virtual exceptions
- * handling asynchronous events
- * enabling/disabling async events
- * parsing start_info struct at start-of-day
- * registering virtual interrupt handlers (for timer interrupts)
- * a simple page and memory allocator
- * minimal libc support
- * minimal Copy-on-Write support
- * network, block, framebuffer support
- * transparent access to FileSystem exports (see tools/fs-back)
-
-- to build it just type make.
-
-- to build it with TCP/IP support, download LWIP 1.3.2 source code and type
-
- make LWIPDIR=/path/to/lwip/source
-
-- to build it with much better libc support, see the stubdom/ directory
-
-- to start it do the following in domain0
- # xl create -c domain_config
-
-This starts the kernel and prints out a bunch of stuff and then once every
-second the system time.
-
-If you have setup a disk in the config file (e.g.
-disk = [ 'file:/tmp/foo,hda,r' ] ), it will loop reading it. If that disk is
-writable (e.g. disk = [ 'file:/tmp/foo,hda,w' ] ), it will write data patterns
-and re-read them.
-
-If you have setup a network in the config file (e.g. vif = [''] ), it will
-print incoming packets.
-
-If you have setup a VFB in the config file (e.g. vfb = ['type=sdl'] ), it will
-show a mouse with which you can draw color squares.
-
-If you have compiled it with TCP/IP support, it will run a daytime server on
-TCP port 13.
+++ /dev/null
-SECTIONS
-{
- .app.bss : {
- __app_bss_start = . ;
- *(.bss .bss.*)
- *(COMMON)
- *(.lbss .lbss.*)
- *(LARGE_COMMON)
- __app_bss_end = . ;
- }
-}
+++ /dev/null
-@ Offset of the kernel within the RAM. This is a Linux/zImage convention which we
-@ rely on for now.
-#define ZIMAGE_KERNEL_OFFSET 0x8000
-
-.section .text
-
-.globl _start
-_start:
- @ zImage header
-.rept 8
- mov r0, r0
-.endr
- b reset
- .word 0x016f2818 @ Magic numbers to help the loader
- .word 0 @ zImage start address (0 = relocatable)
- .word _edata - _start @ zImage end address (excludes bss section)
- @ end of zImage header
-
-@ Called at boot time. Sets up MMU, exception vectors and stack, and then calls C arch_init() function.
-@ => r2 -> DTB
-@ <= never returns
-@ Note: this boot code needs to be within the first (1MB - ZIMAGE_KERNEL_OFFSET) of _start.
-reset:
- @ Problem: the C code wants to be at a known address (_start), but Xen might
- @ load us anywhere. We initialise the MMU (mapping virtual to physical @ addresses)
- @ so everything ends up where the code expects it to be.
- @
- @ We calculate the offet between where the linker thought _start would be and where
- @ it actually is and initialise the page tables to have that offset for every page.
- @
- @ When we turn on the MMU, we're still executing at the old address. We don't want
- @ the code to disappear from under us. So we have to do the mapping in stages:
- @
- @ 1. set up a mapping to our current page from both its current and desired addresses
- @ 2. enable the MMU
- @ 3. jump to the new address
- @ 4. remap all the other pages with the calculated offset
-
- adr r1, _start @ r1 = physical address of _start
- ldr r3, =_start @ r3 = (desired) virtual address of _start
- sub r9, r1, r3 @ r9 = (physical - virtual) offset
-
- ldr r7, =_page_dir @ r7 = (desired) virtual addr of translation table
- add r1, r7, r9 @ r1 = physical addr of translation table
-
- @ Tell the system where our page table is located.
- @ This is the 16 KB top-level translation table, in which
- @ each word maps one 1MB virtual section to a physical section.
- @ Note: We leave TTBCR as 0, meaning that only TTBR0 is used and
- @ we use the short-descriptor format (32-bit physical addresses).
- orr r0, r1, #0b0001011 @ Sharable, Inner/Outer Write-Back Write-Allocate Cacheable
- mcr p15, 0, r0, c2, c0, 0 @ set TTBR0
-
- @ Set access permission for domains.
- @ Domains are deprecated, but we have to configure them anyway.
- @ We mark every page as being domain 0 and set domain 0 to "client mode"
- @ (client mode = use access flags in page table).
- mov r0, #1 @ 1 = client
- mcr p15, 0, r0, c3, c0, 0 @ DACR
-
- @ Template (flags) for a 1 MB page-table entry.
- @ TEX[2:0] C B = 001 1 1 (outer and inner write-back, write-allocate)
- ldr r8, =(0x2 + /* Section entry */ \
- 0xc + /* C B */ \
- (3 << 10) + /* Read/write */ \
- (1 << 12) + /* TEX */ \
- (1 << 16) + /* Sharable */ \
- (1<<19)) /* Non-secure */
- @ r8 = template page table entry
-
- @ Add an entry for the current physical section, at the old and new
- @ addresses. It's OK if they're the same.
- mov r0, pc, lsr#20
- mov r0, r0, lsl#20 @ r0 = physical address of this code's section start
- orr r3, r0, r8 @ r3 = table entry for this section
- ldr r4, =_start @ r4 = desired virtual address of this section
- str r3, [r1, r4, lsr#18] @ map desired virtual section to this code
- str r3, [r1, r0, lsr#18] @ map current section to this code too
-
- @ Invalidate TLB
- dsb @ Caching is off, but must still prevent reordering
- mcr p15, 0, r1, c8, c7, 0 @ TLBIALL
-
- @ Enable MMU / SCTLR
- mrc p15, 0, r1, c1, c0, 0 @ SCTLR
- orr r1, r1, #3 << 11 @ enable icache, branch prediction
- orr r1, r1, #4 + 1 @ enable dcache, MMU
- mcr p15, 0, r1, c1, c0, 0 @ SCTLR
- isb
-
- ldr r1, =stage2 @ Virtual address of stage2
- bx r1
-
-@ Called once the MMU is enabled. The boot code and the page table are mapped,
-@ but nothing else is yet.
-@
-@ => r2 -> dtb (physical)
-@ r7 = virtual address of page table
-@ r8 = section entry template (flags)
-@ r9 = desired physical - virtual offset
-@ pc -> somewhere in newly-mapped virtual code section
-stage2:
- @ Invalidate TLB
- mcr p15, 0, r1, c8, c7, 0 @ TLBIALL
- isb
-
- @ The new mapping has now taken effect:
- @ r7 -> page_dir
-
- @ Fill in the whole top-level translation table (at page_dir).
- @ Populate the whole pagedir with 1MB section descriptors.
-
- mov r1, r7 @ r1 -> first section entry
- add r3, r1, #4*4*1024 @ limit (4 GB address space, 4 byte entries)
- orr r0, r8, r9 @ r0 = entry mapping section zero to start of physical RAM
-1:
- str r0, [r1],#4 @ write the section entry
- add r0, r0, #1 << 20 @ next physical page (wraps)
- cmp r1, r3
- bne 1b
-
- @ Invalidate TLB
- dsb
- mcr p15, 0, r1, c8, c7, 0 @ TLBIALL
- isb
-
- @ Set VBAR -> exception_vector_table
- @ SCTLR.V = 0
- adr r0, exception_vector_table
- mcr p15, 0, r0, c12, c0, 0
-
- @ Enable hardware floating point:
- @ 1. Access to CP10 and CP11 must be enabled in the Coprocessor Access
- @ Control Register (CP15.CACR):
- mrc p15, 0, r1, c1, c0, 2 @ CACR
- orr r1, r1, #(3 << 20) + (3 << 22) @ full access for CP10 & CP11
- mcr p15, 0, r1, c1, c0, 2
- @ 2. The EN bit in the FPEXC register must be set:
- vmrs r0, FPEXC
- orr r0, r0, #1<<30 @ EN (enable)
- vmsr FPEXC, r0
-
- @ Initialise 16 KB stack
- ldr sp, =_boot_stack_end
-
- sub r0, r2, r9 @ r0 -> device tree (virtual address)
- mov r1, r9 @ r1 = physical_address_offset
-
- b arch_init
-
-.pushsection .bss
-@ Note: calling arch_init zeroes out this region.
-.align 12
-.globl shared_info_page
-shared_info_page:
- .fill (1024), 4, 0x0
-
-.align 3
-.globl irqstack
-.globl irqstack_end
-irqstack:
- .fill (1024), 4, 0x0
-irqstack_end:
-
-fault_dump:
- .fill 18, 4, 0x0 @ On fault, we save the registers + CPSR + handler address
-
-.popsection
-
-fault:
- cpsid aif @ Disable interrupts
-
- ldr r13, =fault_dump
- stmia r13, {r0-r12} @ Dump the non-banked registers directly (well, unless from FIQ mode)
- str r14, [r13, #15 << 2] @ Our r14 is the faulting r15
- mov r0, r13
-
- @ Save the caller's CPSR (our SPSR) too.
- mrs r1, SPSR
- str r1, [r13, #16 << 2]
-
- @ Switch to the mode we came from to get r13 and r14.
- @ If coming from user mode, use System mode instead so we're still
- @ privileged.
- and r1, r1, #0x1f @ r1 = SPSR mode
- cmp r1, #0x10 @ If from User mode
- moveq r1, #0x1f @ Then use System mode instead
-
- mrs r3, CPSR @ r3 = our CPSR
- bic r2, r3, #0x1f
- orr r2, r2, r1
- msr CPSR, r2 @ Change to mode r1
-
- @ Save old mode's r13, r14
- str r13, [r0, #13 << 2]
- str r14, [r0, #14 << 2]
-
- msr CPSR, r3 @ Back to fault mode
-
- ldr r1, [r0, #17 << 2]
- sub r1, r1, #12 @ Fix to point at start of handler
- str r1, [r0, #17 << 2]
-
- @ Call C code to format the register dump.
- @ Clobbers the stack, but we're not going to return anyway.
- ldr sp, =_boot_stack_end
- bl dump_registers
- b do_exit
-
-@ We want to store a unique value to identify this handler, without corrupting
-@ any of the registers. So, we store r15 (which will point just after the branch).
-@ Later, we subtract 12 so the user gets pointed at the start of the exception
-@ handler.
-#define FAULT(name) \
-.globl fault_##name; \
-fault_##name: \
- ldr r13, =fault_dump; \
- str r15, [r13, #17 << 2]; \
- b fault
-
-FAULT(reset)
-FAULT(undefined_instruction)
-FAULT(svc)
-FAULT(prefetch_call)
-FAULT(prefetch_abort)
-FAULT(data_abort)
-
-@ exception base address
-.align 5
-.globl exception_vector_table
-@ Note: remember to call CLREX if returning from an exception:
-@ "The architecture enables the local monitor to treat any exclusive store as
-@ matching a previous LDREX address. For this reason, use of the CLREX
-@ instruction to clear an existing tag is required on context switches."
-@ -- ARM Cortex-A Series Programmer’s Guide (Version: 4.0)
-exception_vector_table:
- b fault_reset
- b fault_undefined_instruction
- b fault_svc
- b fault_prefetch_call
- b fault_prefetch_abort
- b fault_data_abort
- b irq_handler @ IRQ
- .word 0xe7f000f0 @ abort on FIQ
-
-@ Call fault_undefined_instruction in "Undefined mode"
-bug:
- .word 0xe7f000f0 @ und/udf - a "Permanently Undefined" instruction
-
-irq_handler:
- ldr sp, =irqstack_end
- push {r0 - r12, r14}
-
- ldr r0, IRQ_handler
- cmp r0, #0
- beq bug
- blx r0 @ call handler
-
- @ Return from IRQ
- pop {r0 - r12, r14}
- clrex
- subs pc, lr, #4
-
-.globl IRQ_handler
-IRQ_handler:
- .long 0x0
-
-
-.globl __arch_switch_threads
-@ => r0 = &prev->sp
-@ r1 = &next->sp
-@ <= returns to next thread's saved return address
-__arch_switch_threads:
- push {r4-r11} @ Store callee-saved registers to old thread's stack
- stmia r0, {sp, lr} @ Store current sp and ip to prev's struct thread
-
- ldmia r1, {sp, lr} @ Load new sp, ip from next's struct thread
- pop {r4-r11} @ Load callee-saved registers from new thread's stack
-
- bx lr
-
-@ This is called if you try to divide by zero. For now, we make a supervisor call,
-@ which will make us halt.
-.globl raise
-raise:
- svc 0
-
-.globl arm_start_thread
-arm_start_thread:
- pop {r0, r1}
- @ r0 = user data
- @ r1 -> thread's main function
- ldr lr, =exit_thread
- bx r1
+++ /dev/null
-#include <mini-os/os.h>
-#include <mini-os/events.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/console.h>
-
-static void virq_debug(evtchn_port_t port, struct pt_regs *regs, void *params)
-{
- printk("Received a virq_debug event\n");
-}
-
-evtchn_port_t debug_port = -1;
-void arch_init_events(void)
-{
- debug_port = bind_virq(VIRQ_DEBUG, (evtchn_handler_t)virq_debug, 0);
- if(debug_port == -1)
- BUG();
- unmask_evtchn(debug_port);
-}
-
-void arch_unbind_ports(void)
-{
- if(debug_port != -1)
- {
- mask_evtchn(debug_port);
- unbind_evtchn(debug_port);
- }
-}
-
-void arch_fini_events(void)
-{
-}
+++ /dev/null
-/******************************************************************************
- * hypercall.S
- *
- * Xen hypercall wrappers
- *
- * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation; or, when distributed
- * separately from the Linux kernel or incorporated into other
- * software packages, subject to the following license:
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this source file (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <xen/xen.h>
-
-#define __HVC(imm16) .long ((0xE1400070 | (((imm16) & 0xFFF0) << 4) | ((imm16) & 0x000F)) & 0xFFFFFFFF)
-
-#define XEN_IMM 0xEA1
-
-#define HYPERCALL_SIMPLE(hypercall) \
-.globl HYPERVISOR_##hypercall; \
-.align 4,0x90; \
-HYPERVISOR_##hypercall: \
- mov r12, #__HYPERVISOR_##hypercall; \
- __HVC(XEN_IMM); \
- mov pc, lr;
-
-#define _hypercall0 HYPERCALL_SIMPLE
-#define _hypercall1 HYPERCALL_SIMPLE
-#define _hypercall2 HYPERCALL_SIMPLE
-#define _hypercall3 HYPERCALL_SIMPLE
-#define _hypercall4 HYPERCALL_SIMPLE
-
-_hypercall2(sched_op);
-_hypercall2(memory_op);
-_hypercall2(event_channel_op);
-_hypercall2(xen_version);
-_hypercall3(console_io);
-_hypercall1(physdev_op);
-_hypercall3(grant_table_op);
-_hypercall3(vcpu_op);
-_hypercall1(sysctl);
-_hypercall1(domctl);
-_hypercall2(hvm_op);
-_hypercall1(xsm_op);
+++ /dev/null
-OUTPUT_ARCH(arm)
-ENTRY(_start)
-SECTIONS
-{
- /* Note: we currently assume that Xen will load the kernel image
- * at start-of-RAM + 0x8000. We use this initial 32 KB for the stack
- * and translation tables.
- */
- _boot_stack = 0x400000; /* 16 KB boot stack */
- _boot_stack_end = 0x404000;
- _page_dir = 0x404000; /* 16 KB translation table */
- . = 0x408000;
- _text = .; /* Text and read-only data */
- .text : {
- *(.text)
- *(.gnu.warning)
- } = 0x9090
-
- _etext = .; /* End of text section */
-
- .rodata : { *(.rodata) *(.rodata.*) }
- . = ALIGN(4096);
- _erodata = .;
-
- /* newlib initialization functions */
- . = ALIGN(32 / 8);
- PROVIDE (__preinit_array_start = .);
- .preinit_array : { *(.preinit_array) }
- PROVIDE (__preinit_array_end = .);
- PROVIDE (__init_array_start = .);
- .init_array : { *(.init_array) }
- PROVIDE (__init_array_end = .);
- PROVIDE (__fini_array_start = .);
- .fini_array : { *(.fini_array) }
- PROVIDE (__fini_array_end = .);
-
- .ctors : {
- __CTOR_LIST__ = .;
- *(.ctors)
- CONSTRUCTORS
- LONG(0)
- __CTOR_END__ = .;
- }
-
- .dtors : {
- __DTOR_LIST__ = .;
- *(.dtors)
- LONG(0)
- __DTOR_END__ = .;
- }
-
- .data : { /* Data */
- *(.data)
- }
-
- /* Note: linker will insert any extra sections here, just before .bss */
-
- .bss : {
- _edata = .; /* End of data included in image */
- /* Nothing after here is included in the zImage's size */
-
- __bss_start = .;
- *(.bss)
- *(.app.bss)
- }
- _end = . ;
-
- /* Sections to be discarded */
- /DISCARD/ : {
- *(.text.exit)
- *(.data.exit)
- *(.exitcall.exit)
- }
-
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
-}
+++ /dev/null
-#include <mini-os/console.h>
-#include <xen/memory.h>
-#include <arch_mm.h>
-#include <mini-os/hypervisor.h>
-#include <libfdt.h>
-#include <lib.h>
-
-uint32_t physical_address_offset;
-
-unsigned long allocate_ondemand(unsigned long n, unsigned long alignment)
-{
- // FIXME
- BUG();
-}
-
-void arch_init_mm(unsigned long *start_pfn_p, unsigned long *max_pfn_p)
-{
- int memory;
- int prop_len = 0;
- const uint64_t *regs;
-
- printk(" _text: %p(VA)\n", &_text);
- printk(" _etext: %p(VA)\n", &_etext);
- printk(" _erodata: %p(VA)\n", &_erodata);
- printk(" _edata: %p(VA)\n", &_edata);
- printk(" stack start: %p(VA)\n", _boot_stack);
- printk(" _end: %p(VA)\n", &_end);
-
- if (fdt_num_mem_rsv(device_tree) != 0)
- printk("WARNING: reserved memory not supported!\n");
-
- memory = fdt_node_offset_by_prop_value(device_tree, -1, "device_type", "memory", sizeof("memory"));
- if (memory < 0) {
- printk("No memory found in FDT!\n");
- BUG();
- }
-
- /* Xen will always provide us at least one bank of memory.
- * Mini-OS will use the first bank for the time-being. */
- regs = fdt_getprop(device_tree, memory, "reg", &prop_len);
-
- /* The property must contain at least the start address
- * and size, each of which is 8-bytes. */
- if (regs == NULL || prop_len < 16) {
- printk("Bad 'reg' property: %p %d\n", regs, prop_len);
- BUG();
- }
-
- unsigned int end = (unsigned int) &_end;
- paddr_t mem_base = fdt64_to_cpu(regs[0]);
- uint64_t mem_size = fdt64_to_cpu(regs[1]);
- printk("Found memory at 0x%llx (len 0x%llx)\n",
- (unsigned long long) mem_base, (unsigned long long) mem_size);
-
- BUG_ON(to_virt(mem_base) > (void *) &_text); /* Our image isn't in our RAM! */
- *start_pfn_p = PFN_UP(to_phys(end));
- uint64_t heap_len = mem_size - (PFN_PHYS(*start_pfn_p) - mem_base);
- *max_pfn_p = *start_pfn_p + PFN_DOWN(heap_len);
-
- printk("Using pages %lu to %lu as free space for heap.\n", *start_pfn_p, *max_pfn_p);
-
- /* The device tree is probably in memory that we're about to hand over to the page
- * allocator, so move it to the end and reserve that space.
- */
- uint32_t fdt_size = fdt_totalsize(device_tree);
- void *new_device_tree = to_virt(((*max_pfn_p << PAGE_SHIFT) - fdt_size) & PAGE_MASK);
- if (new_device_tree != device_tree) {
- memmove(new_device_tree, device_tree, fdt_size);
- }
- device_tree = new_device_tree;
- *max_pfn_p = to_phys(new_device_tree) >> PAGE_SHIFT;
-}
-
-void arch_init_p2m(unsigned long max_pfn)
-{
-}
-
-void arch_init_demand_mapping_area(unsigned long cur_pfn)
-{
-}
-
-/* Get Xen's suggested physical page assignments for the grant table. */
-static paddr_t get_gnttab_base(void)
-{
- int hypervisor;
- int len = 0;
- const uint64_t *regs;
- paddr_t gnttab_base;
-
- hypervisor = fdt_node_offset_by_compatible(device_tree, -1, "xen,xen");
- BUG_ON(hypervisor < 0);
-
- regs = fdt_getprop(device_tree, hypervisor, "reg", &len);
- /* The property contains the address and size, 8-bytes each. */
- if (regs == NULL || len < 16) {
- printk("Bad 'reg' property: %p %d\n", regs, len);
- BUG();
- }
-
- gnttab_base = fdt64_to_cpu(regs[0]);
-
- printk("FDT suggests grant table base %llx\n", (unsigned long long) gnttab_base);
-
- return gnttab_base;
-}
-
-grant_entry_t *arch_init_gnttab(int nr_grant_frames)
-{
- struct xen_add_to_physmap xatp;
- struct gnttab_setup_table setup;
- xen_pfn_t frames[nr_grant_frames];
- paddr_t gnttab_table;
- int i, rc;
-
- gnttab_table = get_gnttab_base();
-
- for (i = 0; i < nr_grant_frames; i++)
- {
- xatp.domid = DOMID_SELF;
- xatp.size = 0; /* Seems to be unused */
- xatp.space = XENMAPSPACE_grant_table;
- xatp.idx = i;
- xatp.gpfn = (gnttab_table >> PAGE_SHIFT) + i;
- rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
- BUG_ON(rc != 0);
- }
-
- setup.dom = DOMID_SELF;
- setup.nr_frames = nr_grant_frames;
- set_xen_guest_handle(setup.frame_list, frames);
- HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
- if (setup.status != 0)
- {
- printk("GNTTABOP_setup_table failed; status = %d\n", setup.status);
- BUG();
- }
-
- return to_virt(gnttab_table);
-}
+++ /dev/null
-/******************************************************************************
- * panic.c
- *
- * Displays a register dump and stack trace for debugging.
- *
- * Copyright (c) 2014, Thomas Leonard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <mini-os/os.h>
-#include <mini-os/console.h>
-#include <arch_mm.h>
-
-extern int irqstack[];
-extern int irqstack_end[];
-
-typedef void handler(void);
-
-extern handler fault_reset;
-extern handler fault_undefined_instruction;
-extern handler fault_svc;
-extern handler fault_prefetch_call;
-extern handler fault_prefetch_abort;
-extern handler fault_data_abort;
-
-void dump_registers(int *saved_registers) {
- static int in_dump = 0;
- int *sp, *stack_top, *x;
- char *fault_name;
- void *fault_handler;
- int i;
-
- if (in_dump)
- {
- printk("Crash while in dump_registers! Not generating a second report.\n");
- return;
- }
-
- in_dump = 1;
-
- fault_handler = (handler *) saved_registers[17];
- if (fault_handler == fault_reset)
- fault_name = "reset";
- else if (fault_handler == fault_undefined_instruction)
- fault_name = "undefined_instruction";
- else if (fault_handler == fault_svc)
- fault_name = "svc";
- else if (fault_handler == fault_prefetch_call)
- fault_name = "prefetch_call";
- else if (fault_handler == fault_prefetch_abort)
- fault_name = "prefetch_abort";
- else if (fault_handler == fault_data_abort)
- fault_name = "data_abort";
- else
- fault_name = "unknown fault type!";
-
- printk("Fault handler at %p called (%s)\n", fault_handler, fault_name);
-
- for (i = 0; i < 16; i++) {
- printk("r%d = %x\n", i, saved_registers[i]);
- }
- printk("CPSR = %x\n", saved_registers[16]);
-
- printk("Stack dump (innermost last)\n");
- sp = (int *) saved_registers[13];
-
- if (sp >= _boot_stack && sp <= _boot_stack_end)
- stack_top = _boot_stack_end; /* The boot stack */
- else if (sp >= irqstack && sp <= irqstack_end)
- stack_top = irqstack_end; /* The IRQ stack */
- else
- stack_top = (int *) ((((unsigned long) sp) | (__STACK_SIZE-1)) + 1); /* A normal thread stack */
-
- for (x = stack_top - 1; x >= sp; x--)
- {
- printk(" [%8p] %8x\n", x, *x);
- }
- printk("End of stack\n");
-
- in_dump = 0;
-}
+++ /dev/null
-#include <mini-os/sched.h>
-#include <mini-os/xmalloc.h>
-#include <mini-os/console.h>
-
-void arm_start_thread(void);
-
-/* The AAPCS requires the callee (e.g. __arch_switch_threads) to preserve r4-r11. */
-#define CALLEE_SAVED_REGISTERS 8
-
-/* Architecture specific setup of thread creation */
-struct thread* arch_create_thread(char *name, void (*function)(void *),
- void *data)
-{
- struct thread *thread;
-
- thread = xmalloc(struct thread);
- /* We can't use lazy allocation here since the trap handler runs on the stack */
- thread->stack = (char *)alloc_pages(STACK_SIZE_PAGE_ORDER);
- thread->name = name;
- printk("Thread \"%s\": pointer: 0x%p, stack: 0x%p\n", name, thread,
- thread->stack);
-
- /* Save pointer to the thread on the stack, used by current macro */
- *((unsigned long *)thread->stack) = (unsigned long)thread;
-
- /* Push the details to pass to arm_start_thread onto the stack. */
- int *sp = (int *) (thread->stack + STACK_SIZE);
- *(--sp) = (int) function;
- *(--sp) = (int) data;
-
- /* We leave room for the 8 callee-saved registers which we will
- * try to restore on thread switch, even though they're not needed
- * for the initial switch. */
- thread->sp = (unsigned long) sp - 4 * CALLEE_SAVED_REGISTERS;
-
- thread->ip = (unsigned long) arm_start_thread;
-
- return thread;
-}
-
-void run_idle_thread(void)
-{
- __asm__ __volatile__ ("mov sp, %0; bx %1"::
- "r"(idle_thread->sp + 4 * CALLEE_SAVED_REGISTERS),
- "r"(idle_thread->ip));
- /* Never arrive here! */
-}
+++ /dev/null
-#include <mini-os/os.h>
-#include <mini-os/kernel.h>
-#include <mini-os/gic.h>
-#include <mini-os/console.h>
-#include <xen/xen.h>
-#include <xen/memory.h>
-#include <xen/hvm/params.h>
-#include <arch_mm.h>
-#include <libfdt.h>
-
-/*
- * This structure contains start-of-day info, such as pagetable base pointer,
- * address of the shared_info structure, and things like that.
- * On x86, the hypervisor passes it to us. On ARM, we fill it in ourselves.
- */
-union start_info_union start_info_union;
-
-/*
- * Shared page for communicating with the hypervisor.
- * Events flags go here, for example.
- */
-shared_info_t *HYPERVISOR_shared_info;
-
-extern char shared_info_page[PAGE_SIZE];
-
-void *device_tree;
-
-static int hvm_get_parameter(int idx, uint64_t *value)
-{
- struct xen_hvm_param xhv;
- int ret;
-
- xhv.domid = DOMID_SELF;
- xhv.index = idx;
- ret = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
- if (ret < 0) {
- BUG();
- }
- *value = xhv.value;
- return ret;
-}
-
-static void get_console(void)
-{
- uint64_t v = -1;
-
- hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
- start_info.console.domU.evtchn = v;
-
- hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v);
- start_info.console.domU.mfn = v;
-
- printk("Console is on port %d\n", start_info.console.domU.evtchn);
- printk("Console ring is at mfn %lx\n", (unsigned long) start_info.console.domU.mfn);
-}
-
-void get_xenbus(void)
-{
- uint64_t value;
-
- if (hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &value))
- BUG();
-
- start_info.store_evtchn = (int)value;
-
- if(hvm_get_parameter(HVM_PARAM_STORE_PFN, &value))
- BUG();
- start_info.store_mfn = (unsigned long)value;
-}
-
-/*
- * INITIAL C ENTRY POINT.
- */
-void arch_init(void *dtb_pointer, uint32_t physical_offset)
-{
- struct xen_add_to_physmap xatp;
- int r;
-
- memset(&__bss_start, 0, &_end - &__bss_start);
-
- physical_address_offset = physical_offset;
-
- xprintk("Virtual -> physical offset = %x\n", physical_address_offset);
-
- xprintk("Checking DTB at %p...\n", dtb_pointer);
-
- if ((r = fdt_check_header(dtb_pointer))) {
- xprintk("Invalid DTB from Xen: %s\n", fdt_strerror(r));
- BUG();
- }
- device_tree = dtb_pointer;
-
- /* Map shared_info page */
- xatp.domid = DOMID_SELF;
- xatp.idx = 0;
- xatp.space = XENMAPSPACE_shared_info;
- xatp.gpfn = virt_to_pfn(shared_info_page);
- if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0)
- BUG();
- HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
-
- /* Fill in start_info */
- get_console();
- get_xenbus();
-
- gic_init();
-
- start_kernel();
-}
-
-void
-arch_fini(void)
-{
-}
-
-void
-arch_do_exit(void)
-{
-}
+++ /dev/null
-#include <mini-os/os.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/events.h>
-#include <mini-os/traps.h>
-#include <mini-os/types.h>
-#include <mini-os/time.h>
-#include <mini-os/lib.h>
-
-//#define VTIMER_DEBUG
-#ifdef VTIMER_DEBUG
-#define DEBUG(_f, _a...) \
- printk("MINI_OS(file=vtimer.c, line=%d) " _f , __LINE__, ## _a)
-#else
-#define DEBUG(_f, _a...) ((void)0)
-#endif
-
-/************************************************************************
- * Time functions
- *************************************************************************/
-
-static uint64_t cntvct_at_init;
-static uint32_t counter_freq;
-
-/* Compute with 96 bit intermediate result: (a*b)/c */
-uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
-{
- union {
- uint64_t ll;
- struct {
- uint32_t low, high;
- } l;
- } u, res;
- uint64_t rl, rh;
-
- u.ll = a;
- rl = (uint64_t)u.l.low * (uint64_t)b;
- rh = (uint64_t)u.l.high * (uint64_t)b;
- rh += (rl >> 32);
- res.l.high = rh / c;
- res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
- return res.ll;
-}
-
-static inline s_time_t ticks_to_ns(uint64_t ticks)
-{
- return muldiv64(ticks, SECONDS(1), counter_freq);
-}
-
-static inline uint64_t ns_to_ticks(s_time_t ns)
-{
- return muldiv64(ns, counter_freq, SECONDS(1));
-}
-
-/* Wall-clock time is not currently available on ARM, so this is always zero for now:
- * http://wiki.xenproject.org/wiki/Xen_ARM_TODO#Expose_Wallclock_time_to_guests
- */
-static struct timespec shadow_ts;
-
-static inline uint64_t read_virtual_count(void)
-{
- uint32_t c_lo, c_hi;
- __asm__ __volatile__("mrrc p15, 1, %0, %1, c14":"=r"(c_lo), "=r"(c_hi));
- return (((uint64_t) c_hi) << 32) + c_lo;
-}
-
-/* monotonic_clock(): returns # of nanoseconds passed since time_init()
- * Note: This function is required to return accurate
- * time even in the absence of multiple timer ticks.
- */
-uint64_t monotonic_clock(void)
-{
- return ticks_to_ns(read_virtual_count() - cntvct_at_init);
-}
-
-int gettimeofday(struct timeval *tv, void *tz)
-{
- uint64_t nsec = monotonic_clock();
- nsec += shadow_ts.tv_nsec;
-
- tv->tv_sec = shadow_ts.tv_sec;
- tv->tv_sec += NSEC_TO_SEC(nsec);
- tv->tv_usec = NSEC_TO_USEC(nsec % 1000000000UL);
-
- return 0;
-}
-
-/* Set the timer and mask. */
-void write_timer_ctl(uint32_t value) {
- __asm__ __volatile__(
- "mcr p15, 0, %0, c14, c3, 1\n"
- "isb"::"r"(value));
-}
-
-void set_vtimer_compare(uint64_t value) {
- DEBUG("New CompareValue : %llx\n", value);
-
- __asm__ __volatile__("mcrr p15, 3, %0, %H0, c14"
- ::"r"(value));
-
- /* Enable timer and unmask the output signal */
- write_timer_ctl(1);
-}
-
-void unset_vtimer_compare(void) {
- /* Disable timer and mask the output signal */
- write_timer_ctl(2);
-}
-
-void block_domain(s_time_t until)
-{
- uint64_t until_count = ns_to_ticks(until) + cntvct_at_init;
- ASSERT(irqs_disabled());
- if (read_virtual_count() < until_count)
- {
- set_vtimer_compare(until_count);
- __asm__ __volatile__("wfi");
- unset_vtimer_compare();
-
- /* Give the IRQ handler a chance to handle whatever woke us up. */
- local_irq_enable();
- local_irq_disable();
- }
-}
-
-void init_time(void)
-{
- printk("Initialising timer interface\n");
-
- __asm__ __volatile__("mrc p15, 0, %0, c14, c0, 0":"=r"(counter_freq));
- cntvct_at_init = read_virtual_count();
- printk("Virtual Count register is %llx, freq = %d Hz\n", cntvct_at_init, counter_freq);
-}
-
-void fini_time(void)
-{
-}
+++ /dev/null
-#
-# x86 architecture specific makefiles.
-# It's is used for x86_32, x86_32y and x86_64
-#
-
-TOPLEVEL_DIR = $(CURDIR)/../..
-include ../../Config.mk
-
-# include arch.mk has to be before mini-os.mk!
-
-include arch.mk
-include ../../minios.mk
-
-# Sources here are all *.c *.S without $(MINIOS_TARGET_ARCH).S
-# This is handled in $(HEAD_ARCH_OBJ)
-ARCH_SRCS := $(wildcard *.c)
-
-# The objects built from the sources.
-ARCH_OBJS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(ARCH_SRCS))
-
-all: $(OBJ_DIR)/$(ARCH_LIB)
-
-# $(HEAD_ARCH_OBJ) is only build here, needed on linking
-# in ../../Makefile.
-$(OBJ_DIR)/$(ARCH_LIB): $(ARCH_OBJS) $(OBJ_DIR)/$(HEAD_ARCH_OBJ)
- $(AR) rv $(OBJ_DIR)/$(ARCH_LIB) $(ARCH_OBJS)
-
-clean:
- rm -f $(OBJ_DIR)/$(ARCH_LIB) $(ARCH_OBJS) $(OBJ_DIR)/$(HEAD_ARCH_OBJ)
-
+++ /dev/null
-#
-# Architecture special makerules for x86 family
-# (including x86_32, x86_32y and x86_64).
-#
-
-ifeq ($(MINIOS_TARGET_ARCH),x86_32)
-ARCH_CFLAGS := -m32 -march=i686
-ARCH_LDFLAGS := -m elf_i386
-ARCH_ASFLAGS := -m32
-EXTRA_INC += $(TARGET_ARCH_FAM)/$(MINIOS_TARGET_ARCH)
-EXTRA_SRC += arch/$(EXTRA_INC)
-endif
-
-ifeq ($(MINIOS_TARGET_ARCH),x86_64)
-ARCH_CFLAGS := -m64 -mno-red-zone -fno-reorder-blocks
-ARCH_CFLAGS += -fno-asynchronous-unwind-tables
-ARCH_ASFLAGS := -m64
-ARCH_LDFLAGS := -m elf_x86_64
-EXTRA_INC += $(TARGET_ARCH_FAM)/$(MINIOS_TARGET_ARCH)
-EXTRA_SRC += arch/$(EXTRA_INC)
-endif
-
+++ /dev/null
-#include <mini-os/os.h>
-#include <mini-os/mm.h>
-#include <mini-os/events.h>
-
-#if defined(__x86_64__)
-char irqstack[2 * STACK_SIZE];
-
-static struct pda
-{
- int irqcount; /* offset 0 (used in x86_64.S) */
- char *irqstackptr; /* 8 */
-} cpu0_pda;
-#endif
-
-void arch_init_events(void)
-{
-#if defined(__x86_64__)
- asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
- wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
- cpu0_pda.irqcount = -1;
- cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE)
- & ~(STACK_SIZE - 1));
-#endif
-}
-
-void arch_unbind_ports(void)
-{
-}
-
-void arch_fini_events(void)
-{
-#if defined(__x86_64__)
- wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */
-#endif
-}
+++ /dev/null
-/*
- * Copyright (C) 2009, Netronome Systems, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-
-#include <mini-os/types.h>
-#include <mini-os/lib.h>
-#include <mini-os/xmalloc.h>
-#include <mini-os/mm.h>
-#include <mini-os/ioremap.h>
-
-/* Map a physical address range into virtual address space with provided
- * flags. Return a virtual address range it is mapped to. */
-static void *__do_ioremap(unsigned long phys_addr, unsigned long size,
- unsigned long prot)
-{
- unsigned long va;
- unsigned long mfns, mfn;
- unsigned long num_pages, offset;
-
- /* allow non page aligned addresses but for mapping we need to align them */
- offset = (phys_addr & ~PAGE_MASK);
- num_pages = (offset + size + PAGE_SIZE - 1) / PAGE_SIZE;
- phys_addr &= PAGE_MASK;
- mfns = mfn = phys_addr >> PAGE_SHIFT;
-
- va = (unsigned long)map_frames_ex(&mfns, num_pages, 0, 1, 1,
- DOMID_IO, NULL, prot);
- return (void *)(va + offset);
-}
-
-void *ioremap(unsigned long phys_addr, unsigned long size)
-{
- return __do_ioremap(phys_addr, size, IO_PROT);
-}
-
-void *ioremap_nocache(unsigned long phys_addr, unsigned long size)
-{
- return __do_ioremap(phys_addr, size, IO_PROT_NOCACHE);
-}
-
-/* Un-map the io-remapped region. Currently no list of existing mappings is
- * maintained, so the caller has to supply the size */
-void iounmap(void *virt_addr, unsigned long size)
-{
- unsigned long num_pages;
- unsigned long va = (unsigned long)virt_addr;
-
- /* work out number of frames to unmap */
- num_pages = ((va & ~PAGE_MASK) + size + PAGE_SIZE - 1) / PAGE_SIZE;
-
- unmap_frames(va & PAGE_MASK, num_pages);
-}
-
-
-
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 indent-tabs-mode:nil -*- */
+++ /dev/null
-#include <mini-os/iorw.h>
-
-void iowrite8(volatile void* addr, uint8_t val)
-{
- *((volatile uint8_t*)addr) = val;
-}
-void iowrite16(volatile void* addr, uint16_t val)
-{
- *((volatile uint16_t*)addr) = val;
-}
-void iowrite32(volatile void* addr, uint32_t val)
-{
- *((volatile uint32_t*)addr) = val;
-}
-void iowrite64(volatile void* addr, uint64_t val)
-{
- *((volatile uint64_t*)addr) = val;
-}
-
-uint8_t ioread8(volatile void* addr)
-{
- return *((volatile uint8_t*) addr);
-}
-uint16_t ioread16(volatile void* addr)
-{
- return *((volatile uint16_t*) addr);
-}
-uint32_t ioread32(volatile void* addr)
-{
- return *((volatile uint32_t*) addr);
-}
-uint64_t ioread64(volatile void* addr)
-{
- return *((volatile uint64_t*) addr);
-}
+++ /dev/null
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(_start)
-SECTIONS
-{
- . = 0x0;
- _text = .; /* Text and read-only data */
- .text : {
- *(.text)
- *(.gnu.warning)
- } = 0x9090
-
- _etext = .; /* End of text section */
-
- .rodata : { *(.rodata) *(.rodata.*) }
- . = ALIGN(4096);
- _erodata = .;
-
- /* newlib initialization functions */
- . = ALIGN(32 / 8);
- PROVIDE (__preinit_array_start = .);
- .preinit_array : { *(.preinit_array) }
- PROVIDE (__preinit_array_end = .);
- PROVIDE (__init_array_start = .);
- .init_array : { *(.init_array) }
- PROVIDE (__init_array_end = .);
- PROVIDE (__fini_array_start = .);
- .fini_array : { *(.fini_array) }
- PROVIDE (__fini_array_end = .);
-
- .ctors : {
- __CTOR_LIST__ = .;
- *(.ctors)
- CONSTRUCTORS
- LONG(0)
- __CTOR_END__ = .;
- }
-
- .dtors : {
- __DTOR_LIST__ = .;
- *(.dtors)
- LONG(0)
- __DTOR_END__ = .;
- }
-
- .data : { /* Data */
- *(.data)
- }
-
- _edata = .; /* End of data section */
-
- __bss_start = .; /* BSS */
- .bss : {
- *(.bss)
- *(.app.bss)
- }
- _end = . ;
-
- /* Sections to be discarded */
- /DISCARD/ : {
- *(.text.exit)
- *(.data.exit)
- *(.exitcall.exit)
- }
-
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
-}
+++ /dev/null
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
-OUTPUT_ARCH(i386:x86-64)
-ENTRY(_start)
-SECTIONS
-{
- . = 0x0;
- _text = .; /* Text and read-only data */
- .text : {
- *(.text)
- *(.gnu.warning)
- } = 0x9090
-
- _etext = .; /* End of text section */
-
- .rodata : { *(.rodata) *(.rodata.*) }
- . = ALIGN(4096);
- _erodata = .;
-
- /* newlib initialization functions */
- . = ALIGN(64 / 8);
- PROVIDE (__preinit_array_start = .);
- .preinit_array : { *(.preinit_array) }
- PROVIDE (__preinit_array_end = .);
- PROVIDE (__init_array_start = .);
- .init_array : { *(.init_array) }
- PROVIDE (__init_array_end = .);
- PROVIDE (__fini_array_start = .);
- .fini_array : { *(.fini_array) }
- PROVIDE (__fini_array_end = .);
-
- .ctors : {
- __CTOR_LIST__ = .;
- *(.ctors)
- CONSTRUCTORS
- QUAD(0)
- __CTOR_END__ = .;
- }
-
- .dtors : {
- __DTOR_LIST__ = .;
- *(.dtors)
- QUAD(0)
- __DTOR_END__ = .;
- }
-
- .data : { /* Data */
- *(.data)
- }
-
- _edata = .; /* End of data section */
-
- __bss_start = .; /* BSS */
- .bss : {
- *(.bss)
- *(.app.bss)
- }
- _end = . ;
-
- /* Sections to be discarded */
- /DISCARD/ : {
- *(.text.exit)
- *(.data.exit)
- *(.exitcall.exit)
- }
-
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
-}
+++ /dev/null
-/*
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
- ****************************************************************************
- *
- * File: mm.c
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes: Grzegorz Milos
- *
- * Date: Aug 2003, chages Aug 2005
- *
- * Environment: Xen Minimal OS
- * Description: memory management related functions
- * contains buddy page allocator from Xen.
- *
- ****************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <mini-os/os.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/mm.h>
-#include <mini-os/types.h>
-#include <mini-os/lib.h>
-#include <mini-os/xmalloc.h>
-#include <xen/memory.h>
-
-#ifdef MM_DEBUG
-#define DEBUG(_f, _a...) \
- printk("MINI_OS(file=mm.c, line=%d) " _f "\n", __LINE__, ## _a)
-#else
-#define DEBUG(_f, _a...) ((void)0)
-#endif
-
-unsigned long *phys_to_machine_mapping;
-unsigned long mfn_zero;
-extern char stack[];
-extern void page_walk(unsigned long va);
-
-/*
- * Make pt_pfn a new 'level' page table frame and hook it into the page
- * table at offset in previous level MFN (pref_l_mfn). pt_pfn is a guest
- * PFN.
- */
-static void new_pt_frame(unsigned long *pt_pfn, unsigned long prev_l_mfn,
- unsigned long offset, unsigned long level)
-{
- pgentry_t *tab = (pgentry_t *)start_info.pt_base;
- unsigned long pt_page = (unsigned long)pfn_to_virt(*pt_pfn);
- pgentry_t prot_e, prot_t;
- mmu_update_t mmu_updates[1];
- int rc;
-
- prot_e = prot_t = 0;
- DEBUG("Allocating new L%d pt frame for pfn=%lx, "
- "prev_l_mfn=%lx, offset=%lx",
- level, *pt_pfn, prev_l_mfn, offset);
-
- /* We need to clear the page, otherwise we might fail to map it
- as a page table page */
- memset((void*) pt_page, 0, PAGE_SIZE);
-
- switch ( level )
- {
- case L1_FRAME:
- prot_e = L1_PROT;
- prot_t = L2_PROT;
- break;
- case L2_FRAME:
- prot_e = L2_PROT;
- prot_t = L3_PROT;
- break;
-#if defined(__x86_64__)
- case L3_FRAME:
- prot_e = L3_PROT;
- prot_t = L4_PROT;
- break;
-#endif
- default:
- printk("new_pt_frame() called with invalid level number %d\n", level);
- do_exit();
- break;
- }
-
- /* Make PFN a page table page */
-#if defined(__x86_64__)
- tab = pte_to_virt(tab[l4_table_offset(pt_page)]);
-#endif
- tab = pte_to_virt(tab[l3_table_offset(pt_page)]);
-
- mmu_updates[0].ptr = (tab[l2_table_offset(pt_page)] & PAGE_MASK) +
- sizeof(pgentry_t) * l1_table_offset(pt_page);
- mmu_updates[0].val = (pgentry_t)pfn_to_mfn(*pt_pfn) << PAGE_SHIFT |
- (prot_e & ~_PAGE_RW);
-
- if ( (rc = HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF)) < 0 )
- {
- printk("ERROR: PTE for new page table page could not be updated\n");
- printk(" mmu_update failed with rc=%d\n", rc);
- do_exit();
- }
-
- /* Hook the new page table page into the hierarchy */
- mmu_updates[0].ptr =
- ((pgentry_t)prev_l_mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
- mmu_updates[0].val = (pgentry_t)pfn_to_mfn(*pt_pfn) << PAGE_SHIFT | prot_t;
-
- if ( (rc = HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF)) < 0 )
- {
- printk("ERROR: mmu_update failed with rc=%d\n", rc);
- do_exit();
- }
-
- *pt_pfn += 1;
-}
-
-/*
- * Checks if a pagetable frame is needed at 'level' to map a given
- * address. Note, this function is specific to the initial page table
- * building.
- */
-static int need_pt_frame(unsigned long va, int level)
-{
- unsigned long hyp_virt_start = HYPERVISOR_VIRT_START;
-#if defined(__x86_64__)
- unsigned long hyp_virt_end = HYPERVISOR_VIRT_END;
-#else
- unsigned long hyp_virt_end = 0xffffffff;
-#endif
-
- /* In general frames will _not_ be needed if they were already
- allocated to map the hypervisor into our VA space */
-#if defined(__x86_64__)
- if ( level == L3_FRAME )
- {
- if ( l4_table_offset(va) >=
- l4_table_offset(hyp_virt_start) &&
- l4_table_offset(va) <=
- l4_table_offset(hyp_virt_end))
- return 0;
- return 1;
- }
- else
-#endif
-
- if ( level == L2_FRAME )
- {
-#if defined(__x86_64__)
- if ( l4_table_offset(va) >=
- l4_table_offset(hyp_virt_start) &&
- l4_table_offset(va) <=
- l4_table_offset(hyp_virt_end))
-#endif
- if ( l3_table_offset(va) >=
- l3_table_offset(hyp_virt_start) &&
- l3_table_offset(va) <=
- l3_table_offset(hyp_virt_end))
- return 0;
-
- return 1;
- }
- else
- /* Always need l1 frames */
- if ( level == L1_FRAME )
- return 1;
-
- printk("ERROR: Unknown frame level %d, hypervisor %llx,%llx\n",
- level, hyp_virt_start, hyp_virt_end);
- return -1;
-}
-
-/*
- * Build the initial pagetable.
- */
-static void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
-{
- unsigned long start_address, end_address;
- unsigned long pfn_to_map, pt_pfn = *start_pfn;
- static mmu_update_t mmu_updates[L1_PAGETABLE_ENTRIES + 1];
- pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
- unsigned long pt_mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
- unsigned long offset;
- int count = 0;
- int rc;
-
- pfn_to_map =
- (start_info.nr_pt_frames - NOT_L1_FRAMES) * L1_PAGETABLE_ENTRIES;
-
- if ( *max_pfn >= virt_to_pfn(HYPERVISOR_VIRT_START) )
- {
- printk("WARNING: Mini-OS trying to use Xen virtual space. "
- "Truncating memory from %dMB to ",
- ((unsigned long)pfn_to_virt(*max_pfn) -
- (unsigned long)&_text)>>20);
- *max_pfn = virt_to_pfn(HYPERVISOR_VIRT_START - PAGE_SIZE);
- printk("%dMB\n",
- ((unsigned long)pfn_to_virt(*max_pfn) -
- (unsigned long)&_text)>>20);
- }
-
- start_address = (unsigned long)pfn_to_virt(pfn_to_map);
- end_address = (unsigned long)pfn_to_virt(*max_pfn);
-
- /* We worked out the virtual memory range to map, now mapping loop */
- printk("Mapping memory range 0x%lx - 0x%lx\n", start_address, end_address);
-
- while ( start_address < end_address )
- {
- tab = (pgentry_t *)start_info.pt_base;
- pt_mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
-
-#if defined(__x86_64__)
- offset = l4_table_offset(start_address);
- /* Need new L3 pt frame */
- if ( !(start_address & L3_MASK) )
- if ( need_pt_frame(start_address, L3_FRAME) )
- new_pt_frame(&pt_pfn, pt_mfn, offset, L3_FRAME);
-
- page = tab[offset];
- pt_mfn = pte_to_mfn(page);
- tab = to_virt(mfn_to_pfn(pt_mfn) << PAGE_SHIFT);
-#endif
- offset = l3_table_offset(start_address);
- /* Need new L2 pt frame */
- if ( !(start_address & L2_MASK) )
- if ( need_pt_frame(start_address, L2_FRAME) )
- new_pt_frame(&pt_pfn, pt_mfn, offset, L2_FRAME);
-
- page = tab[offset];
- pt_mfn = pte_to_mfn(page);
- tab = to_virt(mfn_to_pfn(pt_mfn) << PAGE_SHIFT);
- offset = l2_table_offset(start_address);
- /* Need new L1 pt frame */
- if ( !(start_address & L1_MASK) )
- if ( need_pt_frame(start_address, L1_FRAME) )
- new_pt_frame(&pt_pfn, pt_mfn, offset, L1_FRAME);
-
- page = tab[offset];
- pt_mfn = pte_to_mfn(page);
- offset = l1_table_offset(start_address);
-
- mmu_updates[count].ptr =
- ((pgentry_t)pt_mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
- mmu_updates[count].val =
- (pgentry_t)pfn_to_mfn(pfn_to_map++) << PAGE_SHIFT | L1_PROT;
- count++;
- if ( count == L1_PAGETABLE_ENTRIES || pfn_to_map == *max_pfn )
- {
- rc = HYPERVISOR_mmu_update(mmu_updates, count, NULL, DOMID_SELF);
- if ( rc < 0 )
- {
- printk("ERROR: build_pagetable(): PTE could not be updated\n");
- printk(" mmu_update failed with rc=%d\n", rc);
- do_exit();
- }
- count = 0;
- }
- start_address += PAGE_SIZE;
- }
-
- *start_pfn = pt_pfn;
-}
-
-/*
- * Mark portion of the address space read only.
- */
-extern struct shared_info shared_info;
-static void set_readonly(void *text, void *etext)
-{
- unsigned long start_address =
- ((unsigned long) text + PAGE_SIZE - 1) & PAGE_MASK;
- unsigned long end_address = (unsigned long) etext;
- static mmu_update_t mmu_updates[L1_PAGETABLE_ENTRIES + 1];
- pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
- unsigned long mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
- unsigned long offset;
- int count = 0;
- int rc;
-
- printk("setting %p-%p readonly\n", text, etext);
-
- while ( start_address + PAGE_SIZE <= end_address )
- {
- tab = (pgentry_t *)start_info.pt_base;
- mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
-
-#if defined(__x86_64__)
- offset = l4_table_offset(start_address);
- page = tab[offset];
- mfn = pte_to_mfn(page);
- tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
-#endif
- offset = l3_table_offset(start_address);
- page = tab[offset];
- mfn = pte_to_mfn(page);
- tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
- offset = l2_table_offset(start_address);
- page = tab[offset];
- mfn = pte_to_mfn(page);
- tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
-
- offset = l1_table_offset(start_address);
-
- if ( start_address != (unsigned long)&shared_info )
- {
- mmu_updates[count].ptr =
- ((pgentry_t)mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
- mmu_updates[count].val = tab[offset] & ~_PAGE_RW;
- count++;
- }
- else
- printk("skipped %p\n", start_address);
-
- start_address += PAGE_SIZE;
-
- if ( count == L1_PAGETABLE_ENTRIES ||
- start_address + PAGE_SIZE > end_address )
- {
- rc = HYPERVISOR_mmu_update(mmu_updates, count, NULL, DOMID_SELF);
- if ( rc < 0 )
- {
- printk("ERROR: set_readonly(): PTE could not be updated\n");
- do_exit();
- }
- count = 0;
- }
- }
-
- {
- mmuext_op_t op = {
- .cmd = MMUEXT_TLB_FLUSH_ALL,
- };
- int count;
- HYPERVISOR_mmuext_op(&op, 1, &count, DOMID_SELF);
- }
-}
-
-/*
- * A useful mem testing function. Write the address to every address in the
- * range provided and read back the value. If verbose, print page walk to
- * some VA
- *
- * If we get MEM_TEST_MAX_ERRORS we might as well stop
- */
-#define MEM_TEST_MAX_ERRORS 10
-int mem_test(unsigned long *start_va, unsigned long *end_va, int verbose)
-{
- unsigned long mask = 0x10000;
- unsigned long *pointer;
- int error_count = 0;
-
- /* write values and print page walks */
- if ( verbose && (((unsigned long)start_va) & 0xfffff) )
- {
- printk("MemTest Start: 0x%lx\n", start_va);
- page_walk((unsigned long)start_va);
- }
- for ( pointer = start_va; pointer < end_va; pointer++ )
- {
- if ( verbose && !(((unsigned long)pointer) & 0xfffff) )
- {
- printk("Writing to %lx\n", pointer);
- page_walk((unsigned long)pointer);
- }
- *pointer = (unsigned long)pointer & ~mask;
- }
- if ( verbose && (((unsigned long)end_va) & 0xfffff) )
- {
- printk("MemTest End: %lx\n", end_va-1);
- page_walk((unsigned long)end_va-1);
- }
-
- /* verify values */
- for ( pointer = start_va; pointer < end_va; pointer++ )
- {
- if ( ((unsigned long)pointer & ~mask) != *pointer )
- {
- printk("Read error at 0x%lx. Read: 0x%lx, should read 0x%lx\n",
- (unsigned long)pointer, *pointer,
- ((unsigned long)pointer & ~mask));
- error_count++;
- if ( error_count >= MEM_TEST_MAX_ERRORS )
- {
- printk("mem_test: too many errors\n");
- return -1;
- }
- }
- }
- return 0;
-}
-
-
-/*
- * get the PTE for virtual address va if it exists. Otherwise NULL.
- */
-static pgentry_t *get_pgt(unsigned long va)
-{
- unsigned long mfn;
- pgentry_t *tab;
- unsigned offset;
-
- tab = (pgentry_t *)start_info.pt_base;
- mfn = virt_to_mfn(start_info.pt_base);
-
-#if defined(__x86_64__)
- offset = l4_table_offset(va);
- if ( !(tab[offset] & _PAGE_PRESENT) )
- return NULL;
- mfn = pte_to_mfn(tab[offset]);
- tab = mfn_to_virt(mfn);
-#endif
- offset = l3_table_offset(va);
- if ( !(tab[offset] & _PAGE_PRESENT) )
- return NULL;
- mfn = pte_to_mfn(tab[offset]);
- tab = mfn_to_virt(mfn);
- offset = l2_table_offset(va);
- if ( !(tab[offset] & _PAGE_PRESENT) )
- return NULL;
- mfn = pte_to_mfn(tab[offset]);
- tab = mfn_to_virt(mfn);
- offset = l1_table_offset(va);
- return &tab[offset];
-}
-
-
-/*
- * return a valid PTE for a given virtual address. If PTE does not exist,
- * allocate page-table pages.
- */
-pgentry_t *need_pgt(unsigned long va)
-{
- unsigned long pt_mfn;
- pgentry_t *tab;
- unsigned long pt_pfn;
- unsigned offset;
-
- tab = (pgentry_t *)start_info.pt_base;
- pt_mfn = virt_to_mfn(start_info.pt_base);
-
-#if defined(__x86_64__)
- offset = l4_table_offset(va);
- if ( !(tab[offset] & _PAGE_PRESENT) )
- {
- pt_pfn = virt_to_pfn(alloc_page());
- new_pt_frame(&pt_pfn, pt_mfn, offset, L3_FRAME);
- }
- ASSERT(tab[offset] & _PAGE_PRESENT);
- pt_mfn = pte_to_mfn(tab[offset]);
- tab = mfn_to_virt(pt_mfn);
-#endif
- offset = l3_table_offset(va);
- if ( !(tab[offset] & _PAGE_PRESENT) )
- {
- pt_pfn = virt_to_pfn(alloc_page());
- new_pt_frame(&pt_pfn, pt_mfn, offset, L2_FRAME);
- }
- ASSERT(tab[offset] & _PAGE_PRESENT);
- pt_mfn = pte_to_mfn(tab[offset]);
- tab = mfn_to_virt(pt_mfn);
- offset = l2_table_offset(va);
- if ( !(tab[offset] & _PAGE_PRESENT) )
- {
- pt_pfn = virt_to_pfn(alloc_page());
- new_pt_frame(&pt_pfn, pt_mfn, offset, L1_FRAME);
- }
- ASSERT(tab[offset] & _PAGE_PRESENT);
- pt_mfn = pte_to_mfn(tab[offset]);
- tab = mfn_to_virt(pt_mfn);
-
- offset = l1_table_offset(va);
- return &tab[offset];
-}
-
-/*
- * Reserve an area of virtual address space for mappings and Heap
- */
-static unsigned long demand_map_area_start;
-#ifdef __x86_64__
-#define DEMAND_MAP_PAGES ((128ULL << 30) / PAGE_SIZE)
-#else
-#define DEMAND_MAP_PAGES ((2ULL << 30) / PAGE_SIZE)
-#endif
-
-#ifndef HAVE_LIBC
-#define HEAP_PAGES 0
-#else
-unsigned long heap, brk, heap_mapped, heap_end;
-#ifdef __x86_64__
-#define HEAP_PAGES ((128ULL << 30) / PAGE_SIZE)
-#else
-#define HEAP_PAGES ((1ULL << 30) / PAGE_SIZE)
-#endif
-#endif
-
-void arch_init_demand_mapping_area(unsigned long cur_pfn)
-{
- cur_pfn++;
-
- demand_map_area_start = (unsigned long) pfn_to_virt(cur_pfn);
- cur_pfn += DEMAND_MAP_PAGES;
- printk("Demand map pfns at %lx-%lx.\n",
- demand_map_area_start, pfn_to_virt(cur_pfn));
-
-#ifdef HAVE_LIBC
- cur_pfn++;
- heap_mapped = brk = heap = (unsigned long) pfn_to_virt(cur_pfn);
- cur_pfn += HEAP_PAGES;
- heap_end = (unsigned long) pfn_to_virt(cur_pfn);
- printk("Heap resides at %lx-%lx.\n", brk, heap_end);
-#endif
-}
-
-unsigned long allocate_ondemand(unsigned long n, unsigned long alignment)
-{
- unsigned long x;
- unsigned long y = 0;
-
- /* Find a properly aligned run of n contiguous frames */
- for ( x = 0;
- x <= DEMAND_MAP_PAGES - n;
- x = (x + y + 1 + alignment - 1) & ~(alignment - 1) )
- {
- unsigned long addr = demand_map_area_start + x * PAGE_SIZE;
- pgentry_t *pgt = get_pgt(addr);
- for ( y = 0; y < n; y++, addr += PAGE_SIZE )
- {
- if ( !(addr & L1_MASK) )
- pgt = get_pgt(addr);
- if ( pgt )
- {
- if ( *pgt & _PAGE_PRESENT )
- break;
- pgt++;
- }
- }
- if ( y == n )
- break;
- }
- if ( y != n )
- {
- printk("Failed to find %ld frames!\n", n);
- return 0;
- }
- return demand_map_area_start + x * PAGE_SIZE;
-}
-
-/*
- * Map an array of MFNs contiguously into virtual address space starting at
- * va. map f[i*stride]+i*increment for i in 0..n-1.
- */
-#define MAP_BATCH ((STACK_SIZE / 2) / sizeof(mmu_update_t))
-void do_map_frames(unsigned long va,
- const unsigned long *mfns, unsigned long n,
- unsigned long stride, unsigned long incr,
- domid_t id, int *err, unsigned long prot)
-{
- pgentry_t *pgt = NULL;
- unsigned long done = 0;
- unsigned long i;
- int rc;
-
- if ( !mfns )
- {
- printk("do_map_frames: no mfns supplied\n");
- return;
- }
- DEBUG("va=%p n=0x%lx, mfns[0]=0x%lx stride=0x%lx incr=0x%lx prot=0x%lx\n",
- va, n, mfns[0], stride, incr, prot);
-
- if ( err )
- memset(err, 0x00, n * sizeof(int));
- while ( done < n )
- {
- unsigned long todo;
-
- if ( err )
- todo = 1;
- else
- todo = n - done;
-
- if ( todo > MAP_BATCH )
- todo = MAP_BATCH;
-
- {
- mmu_update_t mmu_updates[todo];
-
- for ( i = 0; i < todo; i++, va += PAGE_SIZE, pgt++)
- {
- if ( !pgt || !(va & L1_MASK) )
- pgt = need_pgt(va);
-
- mmu_updates[i].ptr = virt_to_mach(pgt) | MMU_NORMAL_PT_UPDATE;
- mmu_updates[i].val = ((pgentry_t)(mfns[(done + i) * stride] +
- (done + i) * incr)
- << PAGE_SHIFT) | prot;
- }
-
- rc = HYPERVISOR_mmu_update(mmu_updates, todo, NULL, id);
- if ( rc < 0 )
- {
- if (err)
- err[done * stride] = rc;
- else {
- printk("Map %ld (%lx, ...) at %p failed: %d.\n",
- todo, mfns[done * stride] + done * incr, va, rc);
- do_exit();
- }
- }
- }
- done += todo;
- }
-}
-
-/*
- * Map an array of MFNs contiguous into virtual address space. Virtual
- * addresses are allocated from the on demand area.
- */
-void *map_frames_ex(const unsigned long *mfns, unsigned long n,
- unsigned long stride, unsigned long incr,
- unsigned long alignment,
- domid_t id, int *err, unsigned long prot)
-{
- unsigned long va = allocate_ondemand(n, alignment);
-
- if ( !va )
- return NULL;
-
- do_map_frames(va, mfns, n, stride, incr, id, err, prot);
-
- return (void *)va;
-}
-
-/*
- * Unmap nun_frames frames mapped at virtual address va.
- */
-#define UNMAP_BATCH ((STACK_SIZE / 2) / sizeof(multicall_entry_t))
-int unmap_frames(unsigned long va, unsigned long num_frames)
-{
- int n = UNMAP_BATCH;
- multicall_entry_t call[n];
- int ret;
- int i;
-
- ASSERT(!((unsigned long)va & ~PAGE_MASK));
-
- DEBUG("va=%p, num=0x%lx\n", va, num_frames);
-
- while ( num_frames ) {
- if ( n > num_frames )
- n = num_frames;
-
- for ( i = 0; i < n; i++ )
- {
- int arg = 0;
- /* simply update the PTE for the VA and invalidate TLB */
- call[i].op = __HYPERVISOR_update_va_mapping;
- call[i].args[arg++] = va;
- call[i].args[arg++] = 0;
-#ifdef __i386__
- call[i].args[arg++] = 0;
-#endif
- call[i].args[arg++] = UVMF_INVLPG;
-
- va += PAGE_SIZE;
- }
-
- ret = HYPERVISOR_multicall(call, n);
- if ( ret )
- {
- printk("update_va_mapping hypercall failed with rc=%d.\n", ret);
- return -ret;
- }
-
- for ( i = 0; i < n; i++ )
- {
- if ( call[i].result )
- {
- printk("update_va_mapping failed for with rc=%d.\n", ret);
- return -(call[i].result);
- }
- }
- num_frames -= n;
- }
- return 0;
-}
-
-/*
- * Allocate pages which are contiguous in machine memory.
- * Returns a VA to where they are mapped or 0 on failure.
- *
- * addr_bits indicates if the region has restrictions on where it is
- * located. Typical values are 32 (if for example PCI devices can't access
- * 64bit memory) or 0 for no restrictions.
- *
- * Allocated pages can be freed using the page allocators free_pages()
- * function.
- *
- * based on Linux function xen_create_contiguous_region()
- */
-#define MAX_CONTIG_ORDER 9 /* 2MB */
-unsigned long alloc_contig_pages(int order, unsigned int addr_bits)
-{
- unsigned long in_va, va;
- unsigned long in_frames[1UL << order], out_frames, mfn;
- multicall_entry_t call[1UL << order];
- unsigned int i, num_pages = 1UL << order;
- int ret, exch_success;
-
- /* pass in num_pages 'extends' of size 1 and
- * request 1 extend of size 'order */
- struct xen_memory_exchange exchange = {
- .in = {
- .nr_extents = num_pages,
- .extent_order = 0,
- .domid = DOMID_SELF
- },
- .out = {
- .nr_extents = 1,
- .extent_order = order,
- .address_bits = addr_bits,
- .domid = DOMID_SELF
- },
- .nr_exchanged = 0
- };
-
- if ( order > MAX_CONTIG_ORDER )
- {
- printk("alloc_contig_pages: order too large 0x%x > 0x%x\n",
- order, MAX_CONTIG_ORDER);
- return 0;
- }
-
- /* Allocate some potentially discontiguous pages */
- in_va = alloc_pages(order);
- if ( !in_va )
- {
- printk("alloc_contig_pages: could not get enough pages (order=0x%x\n",
- order);
- return 0;
- }
-
- /* set up arguments for exchange hyper call */
- set_xen_guest_handle(exchange.in.extent_start, in_frames);
- set_xen_guest_handle(exchange.out.extent_start, &out_frames);
-
- /* unmap current frames, keep a list of MFNs */
- for ( i = 0; i < num_pages; i++ )
- {
- int arg = 0;
-
- va = in_va + (PAGE_SIZE * i);
- in_frames[i] = virt_to_mfn(va);
-
- /* update P2M mapping */
- phys_to_machine_mapping[virt_to_pfn(va)] = INVALID_P2M_ENTRY;
-
- /* build multi call */
- call[i].op = __HYPERVISOR_update_va_mapping;
- call[i].args[arg++] = va;
- call[i].args[arg++] = 0;
-#ifdef __i386__
- call[i].args[arg++] = 0;
-#endif
- call[i].args[arg++] = UVMF_INVLPG;
- }
-
- ret = HYPERVISOR_multicall(call, i);
- if ( ret )
- {
- printk("Odd, update_va_mapping hypercall failed with rc=%d.\n", ret);
- return 0;
- }
-
- /* try getting a contig range of MFNs */
- out_frames = virt_to_pfn(in_va); /* PFNs to populate */
- ret = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
- if ( ret ) {
- printk("mem exchanged order=0x%x failed with rc=%d, nr_exchanged=%d\n",
- order, ret, exchange.nr_exchanged);
- /* we still need to return the allocated pages above to the pool
- * ie. map them back into the 1:1 mapping etc. so we continue but
- * in the end return the pages to the page allocator and return 0. */
- exch_success = 0;
- }
- else
- exch_success = 1;
-
- /* map frames into 1:1 and update p2m */
- for ( i = 0; i < num_pages; i++ )
- {
- int arg = 0;
- pte_t pte;
-
- va = in_va + (PAGE_SIZE * i);
- mfn = i < exchange.nr_exchanged ? (out_frames + i) : in_frames[i];
- pte = __pte(mfn << PAGE_SHIFT | L1_PROT);
-
- /* update P2M mapping */
- phys_to_machine_mapping[virt_to_pfn(va)] = mfn;
-
- /* build multi call */
- call[i].op = __HYPERVISOR_update_va_mapping;
- call[i].args[arg++] = va;
-#ifdef __x86_64__
- call[i].args[arg++] = (pgentry_t)pte.pte;
-#else
- call[i].args[arg++] = pte.pte_low;
- call[i].args[arg++] = pte.pte_high;
-#endif
- call[i].args[arg++] = UVMF_INVLPG;
- }
- ret = HYPERVISOR_multicall(call, i);
- if ( ret )
- {
- printk("update_va_mapping hypercall no. 2 failed with rc=%d.\n", ret);
- return 0;
- }
-
- if ( !exch_success )
- {
- /* since the exchanged failed we just free the pages as well */
- free_pages((void *) in_va, order);
- return 0;
- }
-
- return in_va;
-}
-
-/*
- * Clear some of the bootstrap memory
- */
-static void clear_bootstrap(void)
-{
- pte_t nullpte = { };
- int rc;
-
- /* Use first page as the CoW zero page */
- memset(&_text, 0, PAGE_SIZE);
- mfn_zero = virt_to_mfn((unsigned long) &_text);
- if ( (rc = HYPERVISOR_update_va_mapping(0, nullpte, UVMF_INVLPG)) )
- printk("Unable to unmap NULL page. rc=%d\n", rc);
-}
-
-void arch_init_p2m(unsigned long max_pfn)
-{
-#ifdef __x86_64__
-#define L1_P2M_SHIFT 9
-#define L2_P2M_SHIFT 18
-#define L3_P2M_SHIFT 27
-#else
-#define L1_P2M_SHIFT 10
-#define L2_P2M_SHIFT 20
-#define L3_P2M_SHIFT 30
-#endif
-#define L1_P2M_ENTRIES (1 << L1_P2M_SHIFT)
-#define L2_P2M_ENTRIES (1 << (L2_P2M_SHIFT - L1_P2M_SHIFT))
-#define L3_P2M_ENTRIES (1 << (L3_P2M_SHIFT - L2_P2M_SHIFT))
-#define L1_P2M_MASK (L1_P2M_ENTRIES - 1)
-#define L2_P2M_MASK (L2_P2M_ENTRIES - 1)
-#define L3_P2M_MASK (L3_P2M_ENTRIES - 1)
-
- unsigned long *l1_list = NULL, *l2_list = NULL, *l3_list;
- unsigned long pfn;
-
- l3_list = (unsigned long *)alloc_page();
- for ( pfn=0; pfn<max_pfn; pfn++ )
- {
- if ( !(pfn % (L1_P2M_ENTRIES * L2_P2M_ENTRIES)) )
- {
- l2_list = (unsigned long*)alloc_page();
- if ( (pfn >> L3_P2M_SHIFT) > 0 )
- {
- printk("Error: Too many pfns.\n");
- do_exit();
- }
- l3_list[(pfn >> L2_P2M_SHIFT)] = virt_to_mfn(l2_list);
- }
- if ( !(pfn % (L1_P2M_ENTRIES)) )
- {
- l1_list = (unsigned long*)alloc_page();
- l2_list[(pfn >> L1_P2M_SHIFT) & L2_P2M_MASK] =
- virt_to_mfn(l1_list);
- }
-
- l1_list[pfn & L1_P2M_MASK] = pfn_to_mfn(pfn);
- }
- HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
- virt_to_mfn(l3_list);
- HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
-}
-
-void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p)
-{
- unsigned long start_pfn, max_pfn;
-
- printk(" _text: %p(VA)\n", &_text);
- printk(" _etext: %p(VA)\n", &_etext);
- printk(" _erodata: %p(VA)\n", &_erodata);
- printk(" _edata: %p(VA)\n", &_edata);
- printk("stack start: %p(VA)\n", stack);
- printk(" _end: %p(VA)\n", &_end);
-
- /* First page follows page table pages and 3 more pages (store page etc) */
- start_pfn = PFN_UP(to_phys(start_info.pt_base)) +
- start_info.nr_pt_frames + 3;
- max_pfn = start_info.nr_pages;
-
- /* We need room for demand mapping and heap, clip available memory */
-#if defined(__i386__)
- {
- unsigned long virt_pfns = 1 + DEMAND_MAP_PAGES + 1 + HEAP_PAGES;
- if (max_pfn + virt_pfns >= 0x100000)
- max_pfn = 0x100000 - virt_pfns - 1;
- }
-#endif
-
- printk(" start_pfn: %lx\n", start_pfn);
- printk(" max_pfn: %lx\n", max_pfn);
-
- build_pagetable(&start_pfn, &max_pfn);
- clear_bootstrap();
- set_readonly(&_text, &_erodata);
-
- *start_pfn_p = start_pfn;
- *max_pfn_p = max_pfn;
-}
-
-grant_entry_t *arch_init_gnttab(int nr_grant_frames)
-{
- struct gnttab_setup_table setup;
- unsigned long frames[nr_grant_frames];
-
- setup.dom = DOMID_SELF;
- setup.nr_frames = nr_grant_frames;
- set_xen_guest_handle(setup.frame_list, frames);
-
- HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
- return map_frames(frames, nr_grant_frames);
-}
+++ /dev/null
-/*
- ****************************************************************************
- * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
- ****************************************************************************
- *
- * File: sched.c
- * Author: Grzegorz Milos
- * Changes: Robert Kaiser
- *
- * Date: Aug 2005
- *
- * Environment: Xen Minimal OS
- * Description: simple scheduler for Mini-Os
- *
- * The scheduler is non-preemptive (cooperative), and schedules according
- * to Round Robin algorithm.
- *
- ****************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <mini-os/os.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/time.h>
-#include <mini-os/mm.h>
-#include <mini-os/types.h>
-#include <mini-os/lib.h>
-#include <mini-os/xmalloc.h>
-#include <mini-os/list.h>
-#include <mini-os/sched.h>
-#include <mini-os/semaphore.h>
-
-
-#ifdef SCHED_DEBUG
-#define DEBUG(_f, _a...) \
- printk("MINI_OS(file=sched.c, line=%d) " _f "\n", __LINE__, ## _a)
-#else
-#define DEBUG(_f, _a...) ((void)0)
-#endif
-
-
-void dump_stack(struct thread *thread)
-{
- unsigned long *bottom = (unsigned long *)(thread->stack + STACK_SIZE);
- unsigned long *pointer = (unsigned long *)thread->sp;
- int count;
- if(thread == current)
- {
-#ifdef __i386__
- asm("movl %%esp,%0"
- : "=r"(pointer));
-#else
- asm("movq %%rsp,%0"
- : "=r"(pointer));
-#endif
- }
- printk("The stack for \"%s\"\n", thread->name);
- for(count = 0; count < 25 && pointer < bottom; count ++)
- {
- printk("[0x%lx] 0x%lx\n", pointer, *pointer);
- pointer++;
- }
-
- if(pointer < bottom) printk(" ... continues.\n");
-}
-
-/* Gets run when a new thread is scheduled the first time ever,
- defined in x86_[32/64].S */
-extern void thread_starter(void);
-
-/* Pushes the specified value onto the stack of the specified thread */
-static void stack_push(struct thread *thread, unsigned long value)
-{
- thread->sp -= sizeof(unsigned long);
- *((unsigned long *)thread->sp) = value;
-}
-
-/* Architecture specific setup of thread creation */
-struct thread* arch_create_thread(char *name, void (*function)(void *),
- void *data)
-{
- struct thread *thread;
-
- thread = xmalloc(struct thread);
- /* We can't use lazy allocation here since the trap handler runs on the stack */
- thread->stack = (char *)alloc_pages(STACK_SIZE_PAGE_ORDER);
- thread->name = name;
- printk("Thread \"%s\": pointer: 0x%lx, stack: 0x%lx\n", name, thread,
- thread->stack);
-
- thread->sp = (unsigned long)thread->stack + STACK_SIZE;
- /* Save pointer to the thread on the stack, used by current macro */
- *((unsigned long *)thread->stack) = (unsigned long)thread;
-
- /* Must ensure that (%rsp + 8) is 16-byte aligned at the start of thread_starter. */
- thread->sp -= sizeof(unsigned long);
-
- stack_push(thread, (unsigned long) function);
- stack_push(thread, (unsigned long) data);
- thread->ip = (unsigned long) thread_starter;
- return thread;
-}
-
-void run_idle_thread(void)
-{
- /* Switch stacks and run the thread */
-#if defined(__i386__)
- __asm__ __volatile__("mov %0,%%esp\n\t"
- "push %1\n\t"
- "ret"
- :"=m" (idle_thread->sp)
- :"m" (idle_thread->ip));
-#elif defined(__x86_64__)
- __asm__ __volatile__("mov %0,%%rsp\n\t"
- "push %1\n\t"
- "ret"
- :"=m" (idle_thread->sp)
- :"m" (idle_thread->ip));
-#endif
-}
-
-
-
+++ /dev/null
-/******************************************************************************
- * common.c
- *
- * Common stuff special to x86 goes here.
- *
- * Copyright (c) 2002-2003, K A Fraser & R Neugebauer
- * Copyright (c) 2005, Grzegorz Milos, Intel Research Cambridge
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include <mini-os/os.h>
-#include <mini-os/lib.h> /* for printk, memcpy */
-#include <mini-os/kernel.h>
-#include <xen/xen.h>
-
-/*
- * Shared page for communicating with the hypervisor.
- * Events flags go here, for example.
- */
-shared_info_t *HYPERVISOR_shared_info;
-
-/*
- * This structure contains start-of-day info, such as pagetable base pointer,
- * address of the shared_info structure, and things like that.
- */
-union start_info_union start_info_union;
-
-/*
- * Just allocate the kernel stack here. SS:ESP is set up to point here
- * in head.S.
- */
-char stack[2*STACK_SIZE];
-
-extern char shared_info[PAGE_SIZE];
-
-/* Assembler interface fns in entry.S. */
-void hypervisor_callback(void);
-void failsafe_callback(void);
-
-#if defined(__x86_64__)
-#define __pte(x) ((pte_t) { (x) } )
-#else
-#define __pte(x) ({ unsigned long long _x = (x); \
- ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
-#endif
-
-static
-shared_info_t *map_shared_info(unsigned long pa)
-{
- int rc;
-
- if ( (rc = HYPERVISOR_update_va_mapping(
- (unsigned long)shared_info, __pte(pa | 7), UVMF_INVLPG)) )
- {
- printk("Failed to map shared_info!! rc=%d\n", rc);
- do_exit();
- }
- return (shared_info_t *)shared_info;
-}
-
-static inline void fpu_init(void) {
- asm volatile("fninit");
-}
-
-#ifdef __SSE__
-static inline void sse_init(void) {
- unsigned long status = 0x1f80;
- asm volatile("ldmxcsr %0" : : "m" (status));
-}
-#else
-#define sse_init()
-#endif
-
-
-/*
- * INITIAL C ENTRY POINT.
- */
-void
-arch_init(start_info_t *si)
-{
- static char hello[] = "Bootstrapping...\n";
-
- (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
-
- trap_init();
-
- /*Initialize floating point unit */
- fpu_init();
-
- /* Initialize SSE */
- sse_init();
-
- /* Copy the start_info struct to a globally-accessible area. */
- /* WARN: don't do printk before here, it uses information from
- shared_info. Use xprintk instead. */
- memcpy(&start_info, si, sizeof(*si));
-
- /* print out some useful information */
- printk("Xen Minimal OS!\n");
- printk(" start_info: %p(VA)\n", si);
- printk(" nr_pages: 0x%lx\n", si->nr_pages);
- printk(" shared_inf: 0x%08lx(MA)\n", si->shared_info);
- printk(" pt_base: %p(VA)\n", (void *)si->pt_base);
- printk("nr_pt_frames: 0x%lx\n", si->nr_pt_frames);
- printk(" mfn_list: %p(VA)\n", (void *)si->mfn_list);
- printk(" mod_start: 0x%lx(VA)\n", si->mod_start);
- printk(" mod_len: %lu\n", si->mod_len);
- printk(" flags: 0x%x\n", (unsigned int)si->flags);
- printk(" cmd_line: %s\n",
- si->cmd_line ? (const char *)si->cmd_line : "NULL");
- printk(" stack: %p-%p\n", stack, stack + sizeof(stack));
-
- /* set up minimal memory infos */
- phys_to_machine_mapping = (unsigned long *)start_info.mfn_list;
-
- /* Grab the shared_info pointer and put it in a safe place. */
- HYPERVISOR_shared_info = map_shared_info(start_info.shared_info);
-
- /* Set up event and failsafe callback addresses. */
-#ifdef __i386__
- HYPERVISOR_set_callbacks(
- __KERNEL_CS, (unsigned long)hypervisor_callback,
- __KERNEL_CS, (unsigned long)failsafe_callback);
-#else
- HYPERVISOR_set_callbacks(
- (unsigned long)hypervisor_callback,
- (unsigned long)failsafe_callback, 0);
-#endif
-
- start_kernel();
-}
-
-void
-arch_fini(void)
-{
- /* Reset traps */
- trap_fini();
-
-#ifdef __i386__
- HYPERVISOR_set_callbacks(0, 0, 0, 0);
-#else
- HYPERVISOR_set_callbacks(0, 0, 0);
-#endif
-}
-
-void
-arch_do_exit(void)
-{
- stack_walk();
-}
+++ /dev/null
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- * (C) 2002-2003 - Keir Fraser - University of Cambridge
- * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
- * (C) 2006 - Robert Kaiser - FH Wiesbaden
- ****************************************************************************
- *
- * File: time.c
- * Author: Rolf Neugebauer and Keir Fraser
- * Changes: Grzegorz Milos
- *
- * Description: Simple time and timer functions
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-
-#include <mini-os/os.h>
-#include <mini-os/traps.h>
-#include <mini-os/types.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/events.h>
-#include <mini-os/time.h>
-#include <mini-os/lib.h>
-
-/************************************************************************
- * Time functions
- *************************************************************************/
-
-/* These are peridically updated in shared_info, and then copied here. */
-struct shadow_time_info {
- uint64_t tsc_timestamp; /* TSC at last update of time vals. */
- uint64_t system_timestamp; /* Time, in nanosecs, since boot. */
- uint32_t tsc_to_nsec_mul;
- uint32_t tsc_to_usec_mul;
- int tsc_shift;
- uint32_t version;
-};
-static struct timespec shadow_ts;
-static uint32_t shadow_ts_version;
-
-static struct shadow_time_info shadow;
-
-
-#ifndef rmb
-#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
-#endif
-
-#define HANDLE_USEC_OVERFLOW(_tv) \
- do { \
- while ( (_tv)->tv_usec >= 1000000 ) \
- { \
- (_tv)->tv_usec -= 1000000; \
- (_tv)->tv_sec++; \
- } \
- } while ( 0 )
-
-static inline int time_values_up_to_date(void)
-{
- struct vcpu_time_info *src = &HYPERVISOR_shared_info->vcpu_info[0].time;
-
- return (shadow.version == src->version);
-}
-
-
-/*
- * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
- * yielding a 64-bit result.
- */
-static inline uint64_t scale_delta(uint64_t delta, uint32_t mul_frac, int shift)
-{
- uint64_t product;
-#ifdef __i386__
- uint32_t tmp1, tmp2;
-#endif
-
- if ( shift < 0 )
- delta >>= -shift;
- else
- delta <<= shift;
-
-#ifdef __i386__
- __asm__ (
- "mul %5 ; "
- "mov %4,%%eax ; "
- "mov %%edx,%4 ; "
- "mul %5 ; "
- "add %4,%%eax ; "
- "xor %5,%5 ; "
- "adc %5,%%edx ; "
- : "=A" (product), "=r" (tmp1), "=r" (tmp2)
- : "a" ((uint32_t)delta), "1" ((uint32_t)(delta >> 32)), "2" (mul_frac) );
-#else
- __asm__ (
- "mul %%rdx ; shrd $32,%%rdx,%%rax"
- : "=a" (product) : "0" (delta), "d" ((uint64_t)mul_frac) );
-#endif
-
- return product;
-}
-
-
-static unsigned long get_nsec_offset(void)
-{
- uint64_t now, delta;
- rdtscll(now);
- delta = now - shadow.tsc_timestamp;
- return scale_delta(delta, shadow.tsc_to_nsec_mul, shadow.tsc_shift);
-}
-
-
-static void get_time_values_from_xen(void)
-{
- struct vcpu_time_info *src = &HYPERVISOR_shared_info->vcpu_info[0].time;
-
- do {
- shadow.version = src->version;
- rmb();
- shadow.tsc_timestamp = src->tsc_timestamp;
- shadow.system_timestamp = src->system_time;
- shadow.tsc_to_nsec_mul = src->tsc_to_system_mul;
- shadow.tsc_shift = src->tsc_shift;
- rmb();
- }
- while ((src->version & 1) | (shadow.version ^ src->version));
-
- shadow.tsc_to_usec_mul = shadow.tsc_to_nsec_mul / 1000;
-}
-
-
-
-
-/* monotonic_clock(): returns # of nanoseconds passed since time_init()
- * Note: This function is required to return accurate
- * time even in the absence of multiple timer ticks.
- */
-uint64_t monotonic_clock(void)
-{
- uint64_t time;
- uint32_t local_time_version;
-
- do {
- local_time_version = shadow.version;
- rmb();
- time = shadow.system_timestamp + get_nsec_offset();
- if (!time_values_up_to_date())
- get_time_values_from_xen();
- rmb();
- } while (local_time_version != shadow.version);
-
- return time;
-}
-
-static void update_wallclock(void)
-{
- shared_info_t *s = HYPERVISOR_shared_info;
-
- do {
- shadow_ts_version = s->wc_version;
- rmb();
- shadow_ts.tv_sec = s->wc_sec;
- shadow_ts.tv_nsec = s->wc_nsec;
- rmb();
- }
- while ((s->wc_version & 1) | (shadow_ts_version ^ s->wc_version));
-}
-
-
-int gettimeofday(struct timeval *tv, void *tz)
-{
- uint64_t nsec = monotonic_clock();
- nsec += shadow_ts.tv_nsec;
-
-
- tv->tv_sec = shadow_ts.tv_sec;
- tv->tv_sec += NSEC_TO_SEC(nsec);
- tv->tv_usec = NSEC_TO_USEC(nsec % 1000000000UL);
-
- return 0;
-}
-
-
-void block_domain(s_time_t until)
-{
- struct timeval tv;
- gettimeofday(&tv, NULL);
- ASSERT(irqs_disabled());
- if(monotonic_clock() < until)
- {
- HYPERVISOR_set_timer_op(until);
- HYPERVISOR_sched_op(SCHEDOP_block, 0);
- local_irq_disable();
- }
-}
-
-
-/*
- * Just a dummy
- */
-static void timer_handler(evtchn_port_t ev, struct pt_regs *regs, void *ign)
-{
- get_time_values_from_xen();
- update_wallclock();
-}
-
-
-
-static evtchn_port_t port;
-void init_time(void)
-{
- printk("Initialising timer interface\n");
- port = bind_virq(VIRQ_TIMER, &timer_handler, NULL);
- unmask_evtchn(port);
-}
-
-void fini_time(void)
-{
- /* Clear any pending timer */
- HYPERVISOR_set_timer_op(0);
- unbind_evtchn(port);
-}
+++ /dev/null
-
-#include <mini-os/os.h>
-#include <mini-os/traps.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/mm.h>
-#include <mini-os/lib.h>
-#include <mini-os/sched.h>
-
-/*
- * These are assembler stubs in entry.S.
- * They are the actual entry points for virtual exceptions.
- */
-void divide_error(void);
-void debug(void);
-void int3(void);
-void overflow(void);
-void bounds(void);
-void invalid_op(void);
-void device_not_available(void);
-void coprocessor_segment_overrun(void);
-void invalid_TSS(void);
-void segment_not_present(void);
-void stack_segment(void);
-void general_protection(void);
-void page_fault(void);
-void coprocessor_error(void);
-void simd_coprocessor_error(void);
-void alignment_check(void);
-void spurious_interrupt_bug(void);
-void machine_check(void);
-
-
-void dump_regs(struct pt_regs *regs)
-{
- printk("Thread: %s\n", current->name);
-#ifdef __i386__
- printk("EIP: %x, EFLAGS %x.\n", regs->eip, regs->eflags);
- printk("EBX: %08x ECX: %08x EDX: %08x\n",
- regs->ebx, regs->ecx, regs->edx);
- printk("ESI: %08x EDI: %08x EBP: %08x EAX: %08x\n",
- regs->esi, regs->edi, regs->ebp, regs->eax);
- printk("DS: %04x ES: %04x orig_eax: %08x, eip: %08x\n",
- regs->xds, regs->xes, regs->orig_eax, regs->eip);
- printk("CS: %04x EFLAGS: %08x esp: %08x ss: %04x\n",
- regs->xcs, regs->eflags, regs->esp, regs->xss);
-#else
- printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip);
- printk("\nRSP: %04lx:%016lx EFLAGS: %08lx\n",
- regs->ss, regs->rsp, regs->eflags);
- printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
- regs->rax, regs->rbx, regs->rcx);
- printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
- regs->rdx, regs->rsi, regs->rdi);
- printk("RBP: %016lx R08: %016lx R09: %016lx\n",
- regs->rbp, regs->r8, regs->r9);
- printk("R10: %016lx R11: %016lx R12: %016lx\n",
- regs->r10, regs->r11, regs->r12);
- printk("R13: %016lx R14: %016lx R15: %016lx\n",
- regs->r13, regs->r14, regs->r15);
-#endif
-}
-
-static void do_trap(int trapnr, char *str, struct pt_regs * regs, unsigned long error_code)
-{
- printk("FATAL: Unhandled Trap %d (%s), error code=0x%lx\n", trapnr, str, error_code);
- printk("Regs address %p\n", regs);
- dump_regs(regs);
- do_exit();
-}
-
-#define DO_ERROR(trapnr, str, name) \
-void do_##name(struct pt_regs * regs, unsigned long error_code) \
-{ \
- do_trap(trapnr, str, regs, error_code); \
-}
-
-#define DO_ERROR_INFO(trapnr, str, name, sicode, siaddr) \
-void do_##name(struct pt_regs * regs, unsigned long error_code) \
-{ \
- do_trap(trapnr, str, regs, error_code); \
-}
-
-DO_ERROR_INFO( 0, "divide error", divide_error, FPE_INTDIV, regs->eip)
-DO_ERROR( 3, "int3", int3)
-DO_ERROR( 4, "overflow", overflow)
-DO_ERROR( 5, "bounds", bounds)
-DO_ERROR_INFO( 6, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
-DO_ERROR( 7, "device not available", device_not_available)
-DO_ERROR( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
-DO_ERROR(10, "invalid TSS", invalid_TSS)
-DO_ERROR(11, "segment not present", segment_not_present)
-DO_ERROR(12, "stack segment", stack_segment)
-DO_ERROR_INFO(17, "alignment check", alignment_check, BUS_ADRALN, 0)
-DO_ERROR(18, "machine check", machine_check)
-
-void page_walk(unsigned long virt_address)
-{
- pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
- unsigned long addr = virt_address;
- printk("Pagetable walk from virt %lx, base %lx:\n", virt_address, start_info.pt_base);
-
-#if defined(__x86_64__)
- page = tab[l4_table_offset(addr)];
- tab = pte_to_virt(page);
- printk(" L4 = %"PRIpte" (%p) [offset = %lx]\n", page, tab, l4_table_offset(addr));
-#endif
- page = tab[l3_table_offset(addr)];
- tab = pte_to_virt(page);
- printk(" L3 = %"PRIpte" (%p) [offset = %lx]\n", page, tab, l3_table_offset(addr));
- page = tab[l2_table_offset(addr)];
- tab = pte_to_virt(page);
- printk(" L2 = %"PRIpte" (%p) [offset = %lx]\n", page, tab, l2_table_offset(addr));
-
- page = tab[l1_table_offset(addr)];
- printk(" L1 = %"PRIpte" [offset = %lx]\n", page, l1_table_offset(addr));
-
-}
-
-static int handle_cow(unsigned long addr) {
- pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
- unsigned long new_page;
- int rc;
-
-#if defined(__x86_64__)
- page = tab[l4_table_offset(addr)];
- if (!(page & _PAGE_PRESENT))
- return 0;
- tab = pte_to_virt(page);
-#endif
- page = tab[l3_table_offset(addr)];
- if (!(page & _PAGE_PRESENT))
- return 0;
- tab = pte_to_virt(page);
-
- page = tab[l2_table_offset(addr)];
- if (!(page & _PAGE_PRESENT))
- return 0;
- tab = pte_to_virt(page);
-
- page = tab[l1_table_offset(addr)];
- if (!(page & _PAGE_PRESENT))
- return 0;
- /* Only support CoW for the zero page. */
- if (PHYS_PFN(page) != mfn_zero)
- return 0;
-
- new_page = alloc_pages(0);
- memset((void*) new_page, 0, PAGE_SIZE);
-
- rc = HYPERVISOR_update_va_mapping(addr & PAGE_MASK, __pte(virt_to_mach(new_page) | L1_PROT), UVMF_INVLPG);
- if (!rc)
- return 1;
-
- printk("Map zero page to %lx failed: %d.\n", addr, rc);
- return 0;
-}
-
-static void do_stack_walk(unsigned long frame_base)
-{
- unsigned long *frame = (void*) frame_base;
- printk("base is %#lx ", frame_base);
- printk("caller is %#lx\n", frame[1]);
- if (frame[0])
- do_stack_walk(frame[0]);
-}
-
-void stack_walk(void)
-{
- unsigned long bp;
-#ifdef __x86_64__
- asm("movq %%rbp, %0":"=r"(bp));
-#else
- asm("movl %%ebp, %0":"=r"(bp));
-#endif
- do_stack_walk(bp);
-}
-
-static void dump_mem(unsigned long addr)
-{
- unsigned long i;
- if (addr < PAGE_SIZE)
- return;
-
- for (i = ((addr)-16 ) & ~15; i < (((addr)+48 ) & ~15); i++)
- {
- if (!(i%16))
- printk("\n%lx:", i);
- printk(" %02x", *(unsigned char *)i);
- }
- printk("\n");
-}
-#define read_cr2() \
- (HYPERVISOR_shared_info->vcpu_info[smp_processor_id()].arch.cr2)
-
-static int handling_pg_fault = 0;
-
-void do_page_fault(struct pt_regs *regs, unsigned long error_code)
-{
- unsigned long addr = read_cr2();
- struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_crash };
-
- if ((error_code & TRAP_PF_WRITE) && handle_cow(addr))
- return;
-
- /* If we are already handling a page fault, and got another one
- that means we faulted in pagetable walk. Continuing here would cause
- a recursive fault */
- if(handling_pg_fault == 1)
- {
- printk("Page fault in pagetable walk (access to invalid memory?).\n");
- HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
- }
- handling_pg_fault++;
- barrier();
-
-#if defined(__x86_64__)
- printk("Page fault at linear address %p, rip %p, regs %p, sp %p, our_sp %p, code %lx\n",
- addr, regs->rip, regs, regs->rsp, &addr, error_code);
-#else
- printk("Page fault at linear address %p, eip %p, regs %p, sp %p, our_sp %p, code %lx\n",
- addr, regs->eip, regs, regs->esp, &addr, error_code);
-#endif
-
- dump_regs(regs);
-#if defined(__x86_64__)
- do_stack_walk(regs->rbp);
- dump_mem(regs->rsp);
- dump_mem(regs->rbp);
- dump_mem(regs->rip);
-#else
- do_stack_walk(regs->ebp);
- dump_mem(regs->esp);
- dump_mem(regs->ebp);
- dump_mem(regs->eip);
-#endif
- page_walk(addr);
- HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
- /* We should never get here ... but still */
- handling_pg_fault--;
-}
-
-void do_general_protection(struct pt_regs *regs, long error_code)
-{
- struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_crash };
-#ifdef __i386__
- printk("GPF eip: %p, error_code=%lx\n", regs->eip, error_code);
-#else
- printk("GPF rip: %p, error_code=%lx\n", regs->rip, error_code);
-#endif
- dump_regs(regs);
-#if defined(__x86_64__)
- do_stack_walk(regs->rbp);
- dump_mem(regs->rsp);
- dump_mem(regs->rbp);
- dump_mem(regs->rip);
-#else
- do_stack_walk(regs->ebp);
- dump_mem(regs->esp);
- dump_mem(regs->ebp);
- dump_mem(regs->eip);
-#endif
- HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
-}
-
-
-void do_debug(struct pt_regs * regs)
-{
- printk("Debug exception\n");
-#define TF_MASK 0x100
- regs->eflags &= ~TF_MASK;
- dump_regs(regs);
- do_exit();
-}
-
-void do_coprocessor_error(struct pt_regs * regs)
-{
- printk("Copro error\n");
- dump_regs(regs);
- do_exit();
-}
-
-void simd_math_error(void *eip)
-{
- printk("SIMD error\n");
-}
-
-void do_simd_coprocessor_error(struct pt_regs * regs)
-{
- printk("SIMD copro error\n");
-}
-
-void do_spurious_interrupt_bug(struct pt_regs * regs)
-{
-}
-
-/*
- * Submit a virtual IDT to teh hypervisor. This consists of tuples
- * (interrupt vector, privilege ring, CS:EIP of handler).
- * The 'privilege ring' field specifies the least-privileged ring that
- * can trap to that vector using a software-interrupt instruction (INT).
- */
-static trap_info_t trap_table[] = {
- { 0, 0, __KERNEL_CS, (unsigned long)divide_error },
- { 1, 0, __KERNEL_CS, (unsigned long)debug },
- { 3, 3, __KERNEL_CS, (unsigned long)int3 },
- { 4, 3, __KERNEL_CS, (unsigned long)overflow },
- { 5, 3, __KERNEL_CS, (unsigned long)bounds },
- { 6, 0, __KERNEL_CS, (unsigned long)invalid_op },
- { 7, 0, __KERNEL_CS, (unsigned long)device_not_available },
- { 9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
- { 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS },
- { 11, 0, __KERNEL_CS, (unsigned long)segment_not_present },
- { 12, 0, __KERNEL_CS, (unsigned long)stack_segment },
- { 13, 0, __KERNEL_CS, (unsigned long)general_protection },
- { 14, 0, __KERNEL_CS, (unsigned long)page_fault },
- { 15, 0, __KERNEL_CS, (unsigned long)spurious_interrupt_bug },
- { 16, 0, __KERNEL_CS, (unsigned long)coprocessor_error },
- { 17, 0, __KERNEL_CS, (unsigned long)alignment_check },
- { 19, 0, __KERNEL_CS, (unsigned long)simd_coprocessor_error },
- { 0, 0, 0, 0 }
-};
-
-
-
-void trap_init(void)
-{
- HYPERVISOR_set_trap_table(trap_table);
-}
-
-void trap_fini(void)
-{
- HYPERVISOR_set_trap_table(NULL);
-}
+++ /dev/null
-#include <mini-os/os.h>
-#include <mini-os/x86/arch_limits.h>
-#include <xen/arch-x86_32.h>
-
-.section __xen_guest
- .ascii "GUEST_OS=Mini-OS"
- .ascii ",XEN_VER=xen-3.0"
- .ascii ",VIRT_BASE=0x0" /* &_text from minios_x86_32.lds */
- .ascii ",ELF_PADDR_OFFSET=0x0"
- .ascii ",HYPERCALL_PAGE=0x2"
- .ascii ",PAE=yes[extended-cr3]"
- .ascii ",LOADER=generic"
- .byte 0
-.text
-
-.globl _start, shared_info, hypercall_page
-
-_start:
- cld
- lss stack_start,%esp
- andl $(~(__STACK_SIZE-1)), %esp
- push %esi
- call arch_init
-
-stack_start:
- .long stack+(2*__STACK_SIZE), __KERNEL_SS
-
- /* Unpleasant -- the PTE that maps this page is actually overwritten */
- /* to map the real shared-info page! :-) */
- .org 0x1000
-shared_info:
- .org 0x2000
-
-hypercall_page:
- .org 0x3000
-
-ES = 0x20
-ORIG_EAX = 0x24
-EIP = 0x28
-CS = 0x2C
-
-#define ENTRY(X) .globl X ; X :
-
-#define SAVE_ALL \
- cld; \
- pushl %es; \
- pushl %ds; \
- pushl %eax; \
- pushl %ebp; \
- pushl %edi; \
- pushl %esi; \
- pushl %edx; \
- pushl %ecx; \
- pushl %ebx; \
- movl $(__KERNEL_DS),%edx; \
- movl %edx,%ds; \
- movl %edx,%es;
-
-#define RESTORE_ALL \
- popl %ebx; \
- popl %ecx; \
- popl %edx; \
- popl %esi; \
- popl %edi; \
- popl %ebp; \
- popl %eax; \
- popl %ds; \
- popl %es; \
- addl $4,%esp; \
- iret;
-
-ENTRY(divide_error)
- pushl $0 # no error code
- pushl $do_divide_error
-do_exception:
- pushl %ds
- pushl %eax
- xorl %eax, %eax
- pushl %ebp
- pushl %edi
- pushl %esi
- pushl %edx
- decl %eax # eax = -1
- pushl %ecx
- pushl %ebx
- cld
- movl %es, %ecx
- movl ES(%esp), %edi # get the function address
- movl ORIG_EAX(%esp), %edx # get the error code
- movl %eax, ORIG_EAX(%esp)
- movl %ecx, ES(%esp)
- movl $(__KERNEL_DS), %ecx
- movl %ecx, %ds
- movl %ecx, %es
- movl %esp,%eax # pt_regs pointer
- pushl %edx
- pushl %eax
- call *%edi
- jmp ret_from_exception
-
-ret_from_exception:
- movb CS(%esp),%cl
- addl $8,%esp
- RESTORE_ALL
-
-# A note on the "critical region" in our callback handler.
-# We want to avoid stacking callback handlers due to events occurring
-# during handling of the last event. To do this, we keep events disabled
-# until weve done all processing. HOWEVER, we must enable events before
-# popping the stack frame (cant be done atomically) and so it would still
-# be possible to get enough handler activations to overflow the stack.
-# Although unlikely, bugs of that kind are hard to track down, so wed
-# like to avoid the possibility.
-# So, on entry to the handler we detect whether we interrupted an
-# existing activation in its critical region -- if so, we pop the current
-# activation and restart the handler using the previous one.
-ENTRY(hypervisor_callback)
- pushl %eax
- SAVE_ALL
- movl EIP(%esp),%eax
- cmpl $scrit,%eax
- jb 11f
- cmpl $ecrit,%eax
- jb critical_region_fixup
-11: push %esp
- xorl %ebp,%ebp
- call do_hypervisor_callback
- add $4,%esp
- movl HYPERVISOR_shared_info,%esi
- xorl %eax,%eax
- movb CS(%esp),%cl
- test $2,%cl # slow return to ring 2 or 3
- jne safesti
-safesti:movb $0,1(%esi) # reenable event callbacks
-scrit: /**** START OF CRITICAL REGION ****/
- testb $0xFF,(%esi)
- jnz 14f # process more events if necessary...
- RESTORE_ALL
-14: movb $1,1(%esi)
- jmp 11b
-ecrit: /**** END OF CRITICAL REGION ****/
-# [How we do the fixup]. We want to merge the current stack frame with the
-# just-interrupted frame. How we do this depends on where in the critical
-# region the interrupted handler was executing, and so how many saved
-# registers are in each frame. We do this quickly using the lookup table
-# 'critical_fixup_table'. For each byte offset in the critical region, it
-# provides the number of bytes which have already been popped from the
-# interrupted stack frame.
-critical_region_fixup:
- addl $critical_fixup_table-scrit,%eax
- movzbl (%eax),%eax # %eax contains num bytes popped
- mov %esp,%esi
- add %eax,%esi # %esi points at end of src region
- mov %esp,%edi
- add $0x34,%edi # %edi points at end of dst region
- mov %eax,%ecx
- shr $2,%ecx # convert words to bytes
- je 16f # skip loop if nothing to copy
-15: subl $4,%esi # pre-decrementing copy loop
- subl $4,%edi
- movl (%esi),%eax
- movl %eax,(%edi)
- loop 15b
-16: movl %edi,%esp # final %edi is top of merged stack
- jmp 11b
-
-critical_fixup_table:
- .byte 0x00,0x00,0x00 # testb $0xff,(%esi)
- .byte 0x00,0x00 # jne 14f
- .byte 0x00 # pop %ebx
- .byte 0x04 # pop %ecx
- .byte 0x08 # pop %edx
- .byte 0x0c # pop %esi
- .byte 0x10 # pop %edi
- .byte 0x14 # pop %ebp
- .byte 0x18 # pop %eax
- .byte 0x1c # pop %ds
- .byte 0x20 # pop %es
- .byte 0x24,0x24,0x24 # add $4,%esp
- .byte 0x28 # iret
- .byte 0x00,0x00,0x00,0x00 # movb $1,1(%esi)
- .byte 0x00,0x00 # jmp 11b
-
-# Hypervisor uses this for application faults while it executes.
-ENTRY(failsafe_callback)
- pop %ds
- pop %es
- pop %fs
- pop %gs
- iret
-
-ENTRY(coprocessor_error)
- pushl $0
- pushl $do_coprocessor_error
- jmp do_exception
-
-ENTRY(simd_coprocessor_error)
- pushl $0
- pushl $do_simd_coprocessor_error
- jmp do_exception
-
-ENTRY(device_not_available)
- iret
-
-ENTRY(debug)
- pushl $0
- pushl $do_debug
- jmp do_exception
-
-ENTRY(int3)
- pushl $0
- pushl $do_int3
- jmp do_exception
-
-ENTRY(overflow)
- pushl $0
- pushl $do_overflow
- jmp do_exception
-
-ENTRY(bounds)
- pushl $0
- pushl $do_bounds
- jmp do_exception
-
-ENTRY(invalid_op)
- pushl $0
- pushl $do_invalid_op
- jmp do_exception
-
-
-ENTRY(coprocessor_segment_overrun)
- pushl $0
- pushl $do_coprocessor_segment_overrun
- jmp do_exception
-
-
-ENTRY(invalid_TSS)
- pushl $do_invalid_TSS
- jmp do_exception
-
-
-ENTRY(segment_not_present)
- pushl $do_segment_not_present
- jmp do_exception
-
-
-ENTRY(stack_segment)
- pushl $do_stack_segment
- jmp do_exception
-
-
-ENTRY(general_protection)
- pushl $do_general_protection
- jmp do_exception
-
-
-ENTRY(alignment_check)
- pushl $do_alignment_check
- jmp do_exception
-
-
-ENTRY(page_fault)
- pushl $do_page_fault
- jmp do_exception
-
-ENTRY(machine_check)
- pushl $0
- pushl $do_machine_check
- jmp do_exception
-
-
-ENTRY(spurious_interrupt_bug)
- pushl $0
- pushl $do_spurious_interrupt_bug
- jmp do_exception
-
-
-
-ENTRY(thread_starter)
- popl %eax
- popl %ebx
- pushl $0
- xorl %ebp,%ebp
- pushl %eax
- call *%ebx
- call exit_thread
-
-ENTRY(__arch_switch_threads)
- movl 4(%esp), %ecx /* prev */
- movl 8(%esp), %edx /* next */
- pushl %ebp
- pushl %ebx
- pushl %esi
- pushl %edi
- movl %esp, (%ecx) /* save ESP */
- movl (%edx), %esp /* restore ESP */
- movl $1f, 4(%ecx) /* save EIP */
- pushl 4(%edx) /* restore EIP */
- ret
-1:
- popl %edi
- popl %esi
- popl %ebx
- popl %ebp
- ret
+++ /dev/null
-#include <mini-os/os.h>
-#include <mini-os/x86/arch_limits.h>
-#include <xen/features.h>
-
-.section __xen_guest
- .ascii "GUEST_OS=Mini-OS"
- .ascii ",XEN_VER=xen-3.0"
- .ascii ",VIRT_BASE=0x0" /* &_text from minios_x86_64.lds */
- .ascii ",ELF_PADDR_OFFSET=0x0"
- .ascii ",HYPERCALL_PAGE=0x2"
- .ascii ",LOADER=generic"
- .byte 0
-.text
-
-#define ENTRY(X) .globl X ; X :
-.globl _start, shared_info, hypercall_page
-
-
-_start:
- cld
- movq stack_start(%rip),%rsp
- andq $(~(__STACK_SIZE-1)), %rsp
- movq %rsi,%rdi
- call arch_init
-
-stack_start:
- .quad stack+(2*__STACK_SIZE)
-
- /* Unpleasant -- the PTE that maps this page is actually overwritten */
- /* to map the real shared-info page! :-) */
- .org 0x1000
-shared_info:
- .org 0x2000
-
-hypercall_page:
- .org 0x3000
-
-
-#define XEN_GET_VCPU_INFO(reg) movq HYPERVISOR_shared_info,reg
-#define XEN_PUT_VCPU_INFO(reg)
-#define XEN_PUT_VCPU_INFO_fixup
-#define XEN_LOCKED_BLOCK_EVENTS(reg) movb $1,evtchn_upcall_mask(reg)
-#define XEN_LOCKED_UNBLOCK_EVENTS(reg) movb $0,evtchn_upcall_mask(reg)
-#define XEN_TEST_PENDING(reg) testb $0xFF,evtchn_upcall_pending(reg)
-
-#define XEN_BLOCK_EVENTS(reg) XEN_GET_VCPU_INFO(reg) ; \
- XEN_LOCKED_BLOCK_EVENTS(reg) ; \
- XEN_PUT_VCPU_INFO(reg)
-
-#define XEN_UNBLOCK_EVENTS(reg) XEN_GET_VCPU_INFO(reg) ; \
- XEN_LOCKED_UNBLOCK_EVENTS(reg) ; \
- XEN_PUT_VCPU_INFO(reg)
-
-
-/* Offsets into shared_info_t. */
-#define evtchn_upcall_pending /* 0 */
-#define evtchn_upcall_mask 1
-
-NMI_MASK = 0x80000000
-KERNEL_CS_MASK = 0xfc
-
-#define RAX 80
-#define RDI 112
-#define ORIG_RAX 120 /* + error_code */
-#define RIP 128
-#define CS 136
-#define RFLAGS 144
-#define RSP 152
-
-
-/* Macros */
-.macro zeroentry sym
- movq (%rsp),%rcx
- movq 8(%rsp),%r11
- addq $0x10,%rsp /* skip rcx and r11 */
- pushq $0 /* push error code/oldrax */
- pushq %rax /* push real oldrax to the rdi slot */
- leaq \sym(%rip),%rax
- jmp error_entry
-.endm
-
-.macro errorentry sym
- movq (%rsp),%rcx
- movq 8(%rsp),%r11
- addq $0x10,%rsp /* rsp points to the error code */
- pushq %rax
- leaq \sym(%rip),%rax
- jmp error_entry
-.endm
-
-.macro RESTORE_ALL
- movq (%rsp),%r11
- movq 1*8(%rsp),%r10
- movq 2*8(%rsp),%r9
- movq 3*8(%rsp),%r8
- movq 4*8(%rsp),%rax
- movq 5*8(%rsp),%rcx
- movq 6*8(%rsp),%rdx
- movq 7*8(%rsp),%rsi
- movq 8*8(%rsp),%rdi
- addq $9*8+8,%rsp
-.endm
-
-.macro RESTORE_REST
- movq (%rsp),%r15
- movq 1*8(%rsp),%r14
- movq 2*8(%rsp),%r13
- movq 3*8(%rsp),%r12
- movq 4*8(%rsp),%rbp
- movq 5*8(%rsp),%rbx
- addq $6*8,%rsp
-.endm
-
-.macro SAVE_REST
- subq $6*8,%rsp
- movq %rbx,5*8(%rsp)
- movq %rbp,4*8(%rsp)
- movq %r12,3*8(%rsp)
- movq %r13,2*8(%rsp)
- movq %r14,1*8(%rsp)
- movq %r15,(%rsp)
-.endm
-
-.macro HYPERVISOR_IRET flag
- testl $NMI_MASK,2*8(%rsp)
- jnz 2f
-
- /* Direct iret to kernel space. Correct CS and SS. */
- orb $3,1*8(%rsp)
- orb $3,4*8(%rsp)
- iretq
-
-2: /* Slow iret via hypervisor. */
- andl $~NMI_MASK, 16(%rsp)
- pushq $\flag
- jmp hypercall_page + (__HYPERVISOR_iret * 32)
-.endm
-
-
-/*
- * Exception entry point. This expects an error code/orig_rax on the stack
- * and the exception handler in %rax.
- */
-ENTRY(error_entry)
- /* rdi slot contains rax, oldrax contains error code */
- cld
- subq $14*8,%rsp
- movq %rsi,13*8(%rsp)
- movq 14*8(%rsp),%rsi /* load rax from rdi slot */
- movq %rdx,12*8(%rsp)
- movq %rcx,11*8(%rsp)
- movq %rsi,10*8(%rsp) /* store rax */
- movq %r8, 9*8(%rsp)
- movq %r9, 8*8(%rsp)
- movq %r10,7*8(%rsp)
- movq %r11,6*8(%rsp)
- movq %rbx,5*8(%rsp)
- movq %rbp,4*8(%rsp)
- movq %r12,3*8(%rsp)
- movq %r13,2*8(%rsp)
- movq %r14,1*8(%rsp)
- movq %r15,(%rsp)
-
-error_call_handler:
- movq %rdi, RDI(%rsp)
- movq %rsp,%rdi
- movq ORIG_RAX(%rsp),%rsi # get error code
- movq $-1,ORIG_RAX(%rsp)
- call *%rax
- jmp error_exit
-
-
-/*
- * Xen event (virtual interrupt) entry point.
- */
-ENTRY(hypervisor_callback)
- zeroentry hypervisor_callback2
-
-ENTRY(hypervisor_callback2)
- movq %rdi, %rsp
-
- /* check against event re-entrant */
- movq RIP(%rsp),%rax
- cmpq $scrit,%rax
- jb 11f
- cmpq $ecrit,%rax
- jb critical_region_fixup
-
-11: movq %gs:8,%rax
- incl %gs:0
- cmovzq %rax,%rsp
- pushq %rdi
- call do_hypervisor_callback
- popq %rsp
- decl %gs:0
-
-error_exit:
-retint_kernel:
- movl RFLAGS(%rsp), %eax
- shr $9, %eax # EAX[0] == IRET_RFLAGS.IF
- XEN_GET_VCPU_INFO(%rsi)
- andb evtchn_upcall_mask(%rsi),%al
- andb $1,%al # EAX[0] == IRET_RFLAGS.IF & event_mask
- jnz restore_all_enable_events # != 0 => enable event delivery
- XEN_PUT_VCPU_INFO(%rsi)
-
-retint_restore_args:
- RESTORE_REST
- RESTORE_ALL
- HYPERVISOR_IRET 0
-
-restore_all_enable_events:
- RESTORE_REST
- RESTORE_ALL
- pushq %rax # save rax for it will be clobbered later
- RSP_OFFSET=8 # record the stack frame layout changes
- XEN_GET_VCPU_INFO(%rax) # safe to use rax since it is saved
- XEN_UNBLOCK_EVENTS(%rax)
-
-scrit: /**** START OF CRITICAL REGION ****/
- XEN_TEST_PENDING(%rax)
- jz 12f
- XEN_LOCKED_BLOCK_EVENTS(%rax) # if pending, mask events and handle
- # by jumping to hypervisor_prologue
-12: popq %rax # all registers restored from this point
-
-restore_end:
- jnz hypervisor_prologue # safe to jump out of critical region
- # because events are masked if ZF = 0
- HYPERVISOR_IRET 0
-ecrit: /**** END OF CRITICAL REGION ****/
-
-# Set up the stack as Xen does before calling event callback
-hypervisor_prologue:
- pushq %r11
- pushq %rcx
- jmp hypervisor_callback
-
-# [How we do the fixup]. We want to merge the current stack frame with the
-# just-interrupted frame. How we do this depends on where in the critical
-# region the interrupted handler was executing, and so if rax has been
-# restored. We determine by comparing interrupted rip with "restore_end".
-# We always copy all registers below RIP from the current stack frame
-# to the end of the previous activation frame so that we can continue
-# as if we've never even reached 11 running in the old activation frame.
-
-critical_region_fixup:
- # Set up source and destination region pointers
- leaq RIP(%rsp),%rsi # esi points at end of src region
- # Acquire interrupted rsp which was saved-on-stack. This points to
- # the end of dst region. Note that it is not necessarily current rsp
- # plus 0xb0, because the second interrupt might align the stack frame.
- movq RSP(%rsp),%rdi # edi points at end of dst region
-
- cmpq $restore_end,%rax
- jae 13f
-
- # If interrupted rip is before restore_end
- # then rax hasn't been restored yet
- movq (%rdi),%rax
- movq %rax, RAX(%rsp) # save rax
- addq $RSP_OFFSET,%rdi
-
- # Set up the copy
-13: movq $RIP,%rcx
- shr $3,%rcx # convert bytes into count of 64-bit entities
-15: subq $8,%rsi # pre-decrementing copy loop
- subq $8,%rdi
- movq (%rsi),%rax
- movq %rax,(%rdi)
- loop 15b
-16: movq %rdi,%rsp # final rdi is top of merged stack
- andb $KERNEL_CS_MASK,CS(%rsp) # CS might have changed
- jmp 11b
-
-
-
-ENTRY(failsafe_callback)
- popq %rcx
- popq %r11
- iretq
-
-
-ENTRY(coprocessor_error)
- zeroentry do_coprocessor_error
-
-
-ENTRY(simd_coprocessor_error)
- zeroentry do_simd_coprocessor_error
-
-
-ENTRY(device_not_available)
- zeroentry do_device_not_available
-
-
-ENTRY(debug)
- zeroentry do_debug
-
-
-ENTRY(int3)
- zeroentry do_int3
-
-ENTRY(overflow)
- zeroentry do_overflow
-
-
-ENTRY(bounds)
- zeroentry do_bounds
-
-
-ENTRY(invalid_op)
- zeroentry do_invalid_op
-
-
-ENTRY(coprocessor_segment_overrun)
- zeroentry do_coprocessor_segment_overrun
-
-
-ENTRY(invalid_TSS)
- errorentry do_invalid_TSS
-
-
-ENTRY(segment_not_present)
- errorentry do_segment_not_present
-
-
-/* runs on exception stack */
-ENTRY(stack_segment)
- errorentry do_stack_segment
-
-
-ENTRY(general_protection)
- errorentry do_general_protection
-
-
-ENTRY(alignment_check)
- errorentry do_alignment_check
-
-
-ENTRY(divide_error)
- zeroentry do_divide_error
-
-
-ENTRY(spurious_interrupt_bug)
- zeroentry do_spurious_interrupt_bug
-
-
-ENTRY(page_fault)
- errorentry do_page_fault
-
-
-
-
-
-ENTRY(thread_starter)
- popq %rdi
- popq %rbx
- pushq $0
- xorq %rbp,%rbp
- call *%rbx
- call exit_thread
-
-
-ENTRY(__arch_switch_threads)
- pushq %rbp
- pushq %rbx
- pushq %r12
- pushq %r13
- pushq %r14
- pushq %r15
- movq %rsp, (%rdi) /* save ESP */
- movq (%rsi), %rsp /* restore ESP */
- movq $1f, 8(%rdi) /* save EIP */
- pushq 8(%rsi) /* restore EIP */
- ret
-1:
- popq %r15
- popq %r14
- popq %r13
- popq %r12
- popq %rbx
- popq %rbp
- ret
+++ /dev/null
-/* Minimal block driver for Mini-OS.
- * Copyright (c) 2007-2008 Samuel Thibault.
- * Based on netfront.c.
- */
-
-#include <stdint.h>
-#include <mini-os/os.h>
-#include <mini-os/xenbus.h>
-#include <mini-os/events.h>
-#include <errno.h>
-#include <xen/io/blkif.h>
-#include <xen/io/protocols.h>
-#include <mini-os/gnttab.h>
-#include <mini-os/xmalloc.h>
-#include <time.h>
-#include <mini-os/blkfront.h>
-#include <mini-os/lib.h>
-#include <fcntl.h>
-
-#ifndef HAVE_LIBC
-#define strtoul simple_strtoul
-#endif
-
-/* Note: we generally don't need to disable IRQs since we hardly do anything in
- * the interrupt handler. */
-
-/* Note: we really suppose non-preemptive threads. */
-
-DECLARE_WAIT_QUEUE_HEAD(blkfront_queue);
-
-
-
-
-#define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE)
-#define GRANT_INVALID_REF 0
-
-
-struct blk_buffer {
- void* page;
- grant_ref_t gref;
-};
-
-struct blkfront_dev {
- domid_t dom;
-
- struct blkif_front_ring ring;
- grant_ref_t ring_ref;
- evtchn_port_t evtchn;
- blkif_vdev_t handle;
-
- char *nodename;
- char *backend;
- struct blkfront_info info;
-
- xenbus_event_queue events;
-
-#ifdef HAVE_LIBC
- int fd;
-#endif
-};
-
-void blkfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
-{
-#ifdef HAVE_LIBC
- struct blkfront_dev *dev = data;
- int fd = dev->fd;
-
- if (fd != -1)
- files[fd].read = 1;
-#endif
- wake_up(&blkfront_queue);
-}
-
-static void free_blkfront(struct blkfront_dev *dev)
-{
- mask_evtchn(dev->evtchn);
-
- free(dev->backend);
-
- gnttab_end_access(dev->ring_ref);
- free_page(dev->ring.sring);
-
- unbind_evtchn(dev->evtchn);
-
- free(dev->nodename);
- free(dev);
-}
-
-struct blkfront_dev *init_blkfront(char *_nodename, struct blkfront_info *info)
-{
- xenbus_transaction_t xbt;
- char* err;
- char* message=NULL;
- struct blkif_sring *s;
- int retry=0;
- char* msg = NULL;
- char* c;
- char* nodename = _nodename ? _nodename : "device/vbd/768";
-
- struct blkfront_dev *dev;
-
- char path[strlen(nodename) + strlen("/backend-id") + 1];
-
- printk("******************* BLKFRONT for %s **********\n\n\n", nodename);
-
- dev = malloc(sizeof(*dev));
- memset(dev, 0, sizeof(*dev));
- dev->nodename = strdup(nodename);
-#ifdef HAVE_LIBC
- dev->fd = -1;
-#endif
-
- snprintf(path, sizeof(path), "%s/backend-id", nodename);
- dev->dom = xenbus_read_integer(path);
- evtchn_alloc_unbound(dev->dom, blkfront_handler, dev, &dev->evtchn);
-
- s = (struct blkif_sring*) alloc_page();
- memset(s,0,PAGE_SIZE);
-
-
- SHARED_RING_INIT(s);
- FRONT_RING_INIT(&dev->ring, s, PAGE_SIZE);
-
- dev->ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(s),0);
-
- dev->events = NULL;
-
-again:
- err = xenbus_transaction_start(&xbt);
- if (err) {
- printk("starting transaction\n");
- free(err);
- }
-
- err = xenbus_printf(xbt, nodename, "ring-ref","%u",
- dev->ring_ref);
- if (err) {
- message = "writing ring-ref";
- goto abort_transaction;
- }
- err = xenbus_printf(xbt, nodename,
- "event-channel", "%u", dev->evtchn);
- if (err) {
- message = "writing event-channel";
- goto abort_transaction;
- }
- err = xenbus_printf(xbt, nodename,
- "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE);
- if (err) {
- message = "writing protocol";
- goto abort_transaction;
- }
-
- snprintf(path, sizeof(path), "%s/state", nodename);
- err = xenbus_switch_state(xbt, path, XenbusStateConnected);
- if (err) {
- message = "switching state";
- goto abort_transaction;
- }
-
-
- err = xenbus_transaction_end(xbt, 0, &retry);
- free(err);
- if (retry) {
- goto again;
- printk("completing transaction\n");
- }
-
- goto done;
-
-abort_transaction:
- free(err);
- err = xenbus_transaction_end(xbt, 1, &retry);
- printk("Abort transaction %s\n", message);
- goto error;
-
-done:
-
- snprintf(path, sizeof(path), "%s/backend", nodename);
- msg = xenbus_read(XBT_NIL, path, &dev->backend);
- if (msg) {
- printk("Error %s when reading the backend path %s\n", msg, path);
- goto error;
- }
-
- printk("backend at %s\n", dev->backend);
-
- dev->handle = strtoul(strrchr(nodename, '/')+1, NULL, 0);
-
- {
- XenbusState state;
- char path[strlen(dev->backend) + strlen("/feature-flush-cache") + 1];
- snprintf(path, sizeof(path), "%s/mode", dev->backend);
- msg = xenbus_read(XBT_NIL, path, &c);
- if (msg) {
- printk("Error %s when reading the mode\n", msg);
- goto error;
- }
- if (*c == 'w')
- dev->info.mode = O_RDWR;
- else
- dev->info.mode = O_RDONLY;
- free(c);
-
- snprintf(path, sizeof(path), "%s/state", dev->backend);
-
- xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
-
- msg = NULL;
- state = xenbus_read_integer(path);
- while (msg == NULL && state < XenbusStateConnected)
- msg = xenbus_wait_for_state_change(path, &state, &dev->events);
- if (msg != NULL || state != XenbusStateConnected) {
- printk("backend not available, state=%d\n", state);
- xenbus_unwatch_path_token(XBT_NIL, path, path);
- goto error;
- }
-
- snprintf(path, sizeof(path), "%s/info", dev->backend);
- dev->info.info = xenbus_read_integer(path);
-
- snprintf(path, sizeof(path), "%s/sectors", dev->backend);
- // FIXME: read_integer returns an int, so disk size limited to 1TB for now
- dev->info.sectors = xenbus_read_integer(path);
-
- snprintf(path, sizeof(path), "%s/sector-size", dev->backend);
- dev->info.sector_size = xenbus_read_integer(path);
-
- snprintf(path, sizeof(path), "%s/feature-barrier", dev->backend);
- dev->info.barrier = xenbus_read_integer(path);
-
- snprintf(path, sizeof(path), "%s/feature-flush-cache", dev->backend);
- dev->info.flush = xenbus_read_integer(path);
-
- *info = dev->info;
- }
- unmask_evtchn(dev->evtchn);
-
- printk("%u sectors of %u bytes\n", dev->info.sectors, dev->info.sector_size);
- printk("**************************\n");
-
- return dev;
-
-error:
- free(msg);
- free(err);
- free_blkfront(dev);
- return NULL;
-}
-
-void shutdown_blkfront(struct blkfront_dev *dev)
-{
- char* err = NULL, *err2;
- XenbusState state;
-
- char path[strlen(dev->backend) + strlen("/state") + 1];
- char nodename[strlen(dev->nodename) + strlen("/event-channel") + 1];
-
- blkfront_sync(dev);
-
- printk("close blk: backend=%s node=%s\n", dev->backend, dev->nodename);
-
- snprintf(path, sizeof(path), "%s/state", dev->backend);
- snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
-
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
- printk("shutdown_blkfront: error changing state to %d: %s\n",
- XenbusStateClosing, err);
- goto close;
- }
- state = xenbus_read_integer(path);
- while (err == NULL && state < XenbusStateClosing)
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- free(err);
-
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
- printk("shutdown_blkfront: error changing state to %d: %s\n",
- XenbusStateClosed, err);
- goto close;
- }
- state = xenbus_read_integer(path);
- while (state < XenbusStateClosed) {
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- free(err);
- }
-
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
- printk("shutdown_blkfront: error changing state to %d: %s\n",
- XenbusStateInitialising, err);
- goto close;
- }
- state = xenbus_read_integer(path);
- while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
-
-close:
- free(err);
- err2 = xenbus_unwatch_path_token(XBT_NIL, path, path);
- free(err2);
-
- snprintf(nodename, sizeof(nodename), "%s/ring-ref", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
- snprintf(nodename, sizeof(nodename), "%s/event-channel", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
-
- if (!err)
- free_blkfront(dev);
-}
-
-static void blkfront_wait_slot(struct blkfront_dev *dev)
-{
- /* Wait for a slot */
- if (RING_FULL(&dev->ring)) {
- unsigned long flags;
- DEFINE_WAIT(w);
- local_irq_save(flags);
- while (1) {
- blkfront_aio_poll(dev);
- if (!RING_FULL(&dev->ring))
- break;
- /* Really no slot, go to sleep. */
- add_waiter(w, blkfront_queue);
- local_irq_restore(flags);
- schedule();
- local_irq_save(flags);
- }
- remove_waiter(w, blkfront_queue);
- local_irq_restore(flags);
- }
-}
-
-/* Issue an aio */
-void blkfront_aio(struct blkfront_aiocb *aiocbp, int write)
-{
- struct blkfront_dev *dev = aiocbp->aio_dev;
- struct blkif_request *req;
- RING_IDX i;
- int notify;
- int n, j;
- uintptr_t start, end;
-
- // Can't io at non-sector-aligned location
- ASSERT(!(aiocbp->aio_offset & (dev->info.sector_size-1)));
- // Can't io non-sector-sized amounts
- ASSERT(!(aiocbp->aio_nbytes & (dev->info.sector_size-1)));
- // Can't io non-sector-aligned buffer
- ASSERT(!((uintptr_t) aiocbp->aio_buf & (dev->info.sector_size-1)));
-
- start = (uintptr_t)aiocbp->aio_buf & PAGE_MASK;
- end = ((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes + PAGE_SIZE - 1) & PAGE_MASK;
- aiocbp->n = n = (end - start) / PAGE_SIZE;
-
- /* qemu's IDE max multsect is 16 (8KB) and SCSI max DMA was set to 32KB,
- * so max 44KB can't happen */
- ASSERT(n <= BLKIF_MAX_SEGMENTS_PER_REQUEST);
-
- blkfront_wait_slot(dev);
- i = dev->ring.req_prod_pvt;
- req = RING_GET_REQUEST(&dev->ring, i);
-
- req->operation = write ? BLKIF_OP_WRITE : BLKIF_OP_READ;
- req->nr_segments = n;
- req->handle = dev->handle;
- req->id = (uintptr_t) aiocbp;
- req->sector_number = aiocbp->aio_offset / 512;
-
- for (j = 0; j < n; j++) {
- req->seg[j].first_sect = 0;
- req->seg[j].last_sect = PAGE_SIZE / 512 - 1;
- }
- req->seg[0].first_sect = ((uintptr_t)aiocbp->aio_buf & ~PAGE_MASK) / 512;
- req->seg[n-1].last_sect = (((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes - 1) & ~PAGE_MASK) / 512;
- for (j = 0; j < n; j++) {
- uintptr_t data = start + j * PAGE_SIZE;
- if (!write) {
- /* Trigger CoW if needed */
- *(char*)(data + (req->seg[j].first_sect << 9)) = 0;
- barrier();
- }
- aiocbp->gref[j] = req->seg[j].gref =
- gnttab_grant_access(dev->dom, virtual_to_mfn(data), write);
- }
-
- dev->ring.req_prod_pvt = i + 1;
-
- wmb();
- RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify);
-
- if(notify) notify_remote_via_evtchn(dev->evtchn);
-}
-
-static void blkfront_aio_cb(struct blkfront_aiocb *aiocbp, int ret)
-{
- aiocbp->data = (void*) 1;
- aiocbp->aio_cb = NULL;
-}
-
-void blkfront_io(struct blkfront_aiocb *aiocbp, int write)
-{
- unsigned long flags;
- DEFINE_WAIT(w);
-
- ASSERT(!aiocbp->aio_cb);
- aiocbp->aio_cb = blkfront_aio_cb;
- blkfront_aio(aiocbp, write);
- aiocbp->data = NULL;
-
- local_irq_save(flags);
- while (1) {
- blkfront_aio_poll(aiocbp->aio_dev);
- if (aiocbp->data)
- break;
-
- add_waiter(w, blkfront_queue);
- local_irq_restore(flags);
- schedule();
- local_irq_save(flags);
- }
- remove_waiter(w, blkfront_queue);
- local_irq_restore(flags);
-}
-
-static void blkfront_push_operation(struct blkfront_dev *dev, uint8_t op, uint64_t id)
-{
- int i;
- struct blkif_request *req;
- int notify;
-
- blkfront_wait_slot(dev);
- i = dev->ring.req_prod_pvt;
- req = RING_GET_REQUEST(&dev->ring, i);
- req->operation = op;
- req->nr_segments = 0;
- req->handle = dev->handle;
- req->id = id;
- /* Not needed anyway, but the backend will check it */
- req->sector_number = 0;
- dev->ring.req_prod_pvt = i + 1;
- wmb();
- RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify);
- if (notify) notify_remote_via_evtchn(dev->evtchn);
-}
-
-void blkfront_aio_push_operation(struct blkfront_aiocb *aiocbp, uint8_t op)
-{
- struct blkfront_dev *dev = aiocbp->aio_dev;
- blkfront_push_operation(dev, op, (uintptr_t) aiocbp);
-}
-
-void blkfront_sync(struct blkfront_dev *dev)
-{
- unsigned long flags;
- DEFINE_WAIT(w);
-
- if (dev->info.mode == O_RDWR) {
- if (dev->info.barrier == 1)
- blkfront_push_operation(dev, BLKIF_OP_WRITE_BARRIER, 0);
-
- if (dev->info.flush == 1)
- blkfront_push_operation(dev, BLKIF_OP_FLUSH_DISKCACHE, 0);
- }
-
- /* Note: This won't finish if another thread enqueues requests. */
- local_irq_save(flags);
- while (1) {
- blkfront_aio_poll(dev);
- if (RING_FREE_REQUESTS(&dev->ring) == RING_SIZE(&dev->ring))
- break;
-
- add_waiter(w, blkfront_queue);
- local_irq_restore(flags);
- schedule();
- local_irq_save(flags);
- }
- remove_waiter(w, blkfront_queue);
- local_irq_restore(flags);
-}
-
-int blkfront_aio_poll(struct blkfront_dev *dev)
-{
- RING_IDX rp, cons;
- struct blkif_response *rsp;
- int more;
- int nr_consumed;
-
-moretodo:
-#ifdef HAVE_LIBC
- if (dev->fd != -1) {
- files[dev->fd].read = 0;
- mb(); /* Make sure to let the handler set read to 1 before we start looking at the ring */
- }
-#endif
-
- rp = dev->ring.sring->rsp_prod;
- rmb(); /* Ensure we see queued responses up to 'rp'. */
- cons = dev->ring.rsp_cons;
-
- nr_consumed = 0;
- while ((cons != rp))
- {
- struct blkfront_aiocb *aiocbp;
- int status;
-
- rsp = RING_GET_RESPONSE(&dev->ring, cons);
- nr_consumed++;
-
- aiocbp = (void*) (uintptr_t) rsp->id;
- status = rsp->status;
-
- switch (rsp->operation) {
- case BLKIF_OP_READ:
- case BLKIF_OP_WRITE:
- {
- int j;
-
- if (status != BLKIF_RSP_OKAY)
- printk("%s error %d on %s at offset %llu, num bytes %llu\n",
- rsp->operation == BLKIF_OP_READ?"read":"write",
- status, aiocbp->aio_dev->nodename,
- (unsigned long long) aiocbp->aio_offset,
- (unsigned long long) aiocbp->aio_nbytes);
-
- for (j = 0; j < aiocbp->n; j++)
- gnttab_end_access(aiocbp->gref[j]);
-
- break;
- }
-
- case BLKIF_OP_WRITE_BARRIER:
- if (status != BLKIF_RSP_OKAY)
- printk("write barrier error %d\n", status);
- break;
- case BLKIF_OP_FLUSH_DISKCACHE:
- if (status != BLKIF_RSP_OKAY)
- printk("flush error %d\n", status);
- break;
-
- default:
- printk("unrecognized block operation %d response (status %d)\n", rsp->operation, status);
- break;
- }
-
- dev->ring.rsp_cons = ++cons;
- /* Nota: callback frees aiocbp itself */
- if (aiocbp && aiocbp->aio_cb)
- aiocbp->aio_cb(aiocbp, status ? -EIO : 0);
- if (dev->ring.rsp_cons != cons)
- /* We reentered, we must not continue here */
- break;
- }
-
- RING_FINAL_CHECK_FOR_RESPONSES(&dev->ring, more);
- if (more) goto moretodo;
-
- return nr_consumed;
-}
-
-#ifdef HAVE_LIBC
-int blkfront_open(struct blkfront_dev *dev)
-{
- /* Silently prevent multiple opens */
- if(dev->fd != -1) {
- return dev->fd;
- }
- dev->fd = alloc_fd(FTYPE_BLK);
- printk("blk_open(%s) -> %d\n", dev->nodename, dev->fd);
- files[dev->fd].blk.dev = dev;
- files[dev->fd].blk.offset = 0;
- return dev->fd;
-}
-
-int blkfront_posix_rwop(int fd, uint8_t* buf, size_t count, int write)
-{
- struct blkfront_dev* dev = files[fd].blk.dev;
- off_t offset = files[fd].blk.offset;
- struct blkfront_aiocb aiocb;
- unsigned long long disksize = dev->info.sectors * dev->info.sector_size;
- unsigned int blocksize = dev->info.sector_size;
-
- int blknum;
- int blkoff;
- size_t bytes;
- int rc = 0;
- int alignedbuf = 0;
- uint8_t* copybuf = NULL;
-
- /* RW 0 bytes is just a NOP */
- if(count == 0) {
- return 0;
- }
- /* Check for NULL buffer */
- if( buf == NULL ) {
- errno = EFAULT;
- return -1;
- }
-
- /* Write mode checks */
- if(write) {
- /*Make sure we have write permission */
- if(dev->info.info & VDISK_READONLY
- || (dev->info.mode != O_RDWR && dev->info.mode != O_WRONLY)) {
- errno = EACCES;
- return -1;
- }
- /*Make sure disk is big enough for this write */
- if(offset + count > disksize) {
- errno = ENOSPC;
- return -1;
- }
- }
- /* Read mode checks */
- else
- {
- /* Reading past the disk? Just return 0 */
- if(offset >= disksize) {
- return 0;
- }
-
- /*If the requested read is bigger than the disk, just
- * read as much as we can until the end */
- if(offset + count > disksize) {
- count = disksize - offset;
- }
- }
- /* Determine which block to start at and at which offset inside of it */
- blknum = offset / blocksize;
- blkoff = offset % blocksize;
-
- /* Optimization: We need to check if buf is aligned to the sector size.
- * This is somewhat tricky code. We have to add the blocksize - block offset
- * because the first block may be a partial block and then for every subsequent
- * block rw the buffer will be offset.*/
- if(!((uintptr_t) (buf +(blocksize - blkoff)) & (dev->info.sector_size-1))) {
- alignedbuf = 1;
- }
-
- /* Setup aiocb block object */
- aiocb.aio_dev = dev;
- aiocb.aio_offset = blknum * blocksize;
- aiocb.aio_cb = NULL;
- aiocb.data = NULL;
-
- /* If our buffer is unaligned or its aligned but we will need to rw a partial block
- * then a copy will have to be done */
- if(!alignedbuf || blkoff != 0 || count % blocksize != 0) {
- copybuf = _xmalloc(blocksize, dev->info.sector_size);
- }
-
- rc = count;
- while(count > 0) {
- /* determine how many bytes to read/write from/to the current block buffer */
- if(!alignedbuf || blkoff != 0 || count < blocksize) {
- /* This is the case for unaligned R/W or partial block */
- bytes = count < blocksize - blkoff ? count : blocksize - blkoff;
- aiocb.aio_nbytes = blocksize;
- } else {
- /* We can optimize further if buffer is page aligned */
- int not_page_aligned = 0;
- if(((uintptr_t)buf) & (PAGE_SIZE -1)) {
- not_page_aligned = 1;
- }
-
- /* For an aligned R/W we can read up to the maximum transfer size */
- bytes = count > (BLKIF_MAX_SEGMENTS_PER_REQUEST-not_page_aligned)*PAGE_SIZE
- ? (BLKIF_MAX_SEGMENTS_PER_REQUEST-not_page_aligned)*PAGE_SIZE
- : count & ~(blocksize -1);
- aiocb.aio_nbytes = bytes;
- }
-
- /* read operation */
- if(!write) {
- if (alignedbuf && bytes >= blocksize) {
- /* If aligned and were reading a whole block, just read right into buf */
- aiocb.aio_buf = buf;
- blkfront_read(&aiocb);
- } else {
- /* If not then we have to do a copy */
- aiocb.aio_buf = copybuf;
- blkfront_read(&aiocb);
- memcpy(buf, ©buf[blkoff], bytes);
- }
- }
- /* Write operation */
- else {
- if(alignedbuf && bytes >= blocksize) {
- /* If aligned and were writing a whole block, just write directly from buf */
- aiocb.aio_buf = buf;
- blkfront_write(&aiocb);
- } else {
- /* If not then we have to do a copy. */
- aiocb.aio_buf = copybuf;
- /* If we're writing a partial block, we need to read the current contents first
- * so we don't overwrite the extra bits with garbage */
- if(blkoff != 0 || bytes < blocksize) {
- blkfront_read(&aiocb);
- }
- memcpy(©buf[blkoff], buf, bytes);
- blkfront_write(&aiocb);
- }
- }
- /* Will start at beginning of all remaining blocks */
- blkoff = 0;
-
- /* Increment counters and continue */
- count -= bytes;
- buf += bytes;
- if(bytes < blocksize) {
- //At minimum we read one block
- aiocb.aio_offset += blocksize;
- } else {
- //If we read more than a block, was a multiple of blocksize
- aiocb.aio_offset += bytes;
- }
- }
-
- free(copybuf);
- files[fd].blk.offset += rc;
- return rc;
-
-}
-
-int blkfront_posix_fstat(int fd, struct stat* buf)
-{
- struct blkfront_dev* dev = files[fd].blk.dev;
-
- buf->st_mode = dev->info.mode;
- buf->st_uid = 0;
- buf->st_gid = 0;
- buf->st_size = dev->info.sectors * dev->info.sector_size;
- buf->st_atime = buf->st_mtime = buf->st_ctime = time(NULL);
-
- return 0;
-}
-#endif
+++ /dev/null
-include $(MINI-OS_ROOT)/config/StdGNU.mk
-include $(MINI-OS_ROOT)/Config.mk
-CFLAGS += $(DEF_CFLAGS) $(ARCH_CFLAGS)
-CPPFLAGS += $(DEF_CPPFLAGS) $(ARCH_CPPFLAGS) $(extra_incl)
-ASFLAGS += $(DEF_ASFLAGS) $(ARCH_ASFLAGS)
-LDFLAGS += $(DEF_LDFLAGS) $(ARCH_LDFLAGS)
-
-# Override settings for this OS
-PTHREAD_LIBS =
-nosharedlibs=y
+++ /dev/null
-AS = $(CROSS_COMPILE)as
-LD = $(CROSS_COMPILE)ld
-ifeq ($(clang),y)
-CC = $(CROSS_COMPILE)clang
-LD_LTO = $(CROSS_COMPILE)llvm-ld
-else
-CC = $(CROSS_COMPILE)gcc
-LD_LTO = $(CROSS_COMPILE)ld
-endif
-CPP = $(CC) -E
-AR = $(CROSS_COMPILE)ar
-RANLIB = $(CROSS_COMPILE)ranlib
-NM = $(CROSS_COMPILE)nm
-STRIP = $(CROSS_COMPILE)strip
-OBJCOPY = $(CROSS_COMPILE)objcopy
-OBJDUMP = $(CROSS_COMPILE)objdump
-SIZEUTIL = $(CROSS_COMPILE)size
-
-# Allow git to be wrappered in the environment
-GIT ?= git
-
-INSTALL = install
-INSTALL_DIR = $(INSTALL) -d -m0755 -p
-INSTALL_DATA = $(INSTALL) -m0644 -p
-INSTALL_PROG = $(INSTALL) -m0755 -p
-
-BOOT_DIR ?= /boot
-
-SOCKET_LIBS =
-UTIL_LIBS = -lutil
-DLOPEN_LIBS = -ldl
-
-SONAME_LDFLAG = -soname
-SHLIB_LDFLAGS = -shared
-
-ifneq ($(debug),y)
-CFLAGS += -O2 -fomit-frame-pointer
-else
-# Less than -O1 produces bad code and large stack frames
-CFLAGS += -O1 -fno-omit-frame-pointer
-CFLAGS-$(gcc) += -fno-optimize-sibling-calls
-endif
-
-ifeq ($(lto),y)
-CFLAGS += -flto
-LDFLAGS-$(clang) += -plugin LLVMgold.so
-endif
+++ /dev/null
-CONFIG_ARM := y
-CONFIG_ARM_32 := y
-CONFIG_ARM_$(XEN_OS) := y
-
-CONFIG_XEN_INSTALL_SUFFIX :=
-
-# -march= -mcpu=
-
-# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
-CFLAGS += -marm
-
-HAS_PL011 := y
-HAS_EXYNOS4210 := y
-HAS_OMAP := y
-HAS_NS16550 := y
-
-# Use only if calling $(LD) directly.
-LDFLAGS_DIRECT += -EL
-
-CONFIG_LOAD_ADDRESS ?= 0x80000000
-
-IOEMU_CPU_ARCH ?= arm
+++ /dev/null
-CONFIG_ARM := y
-CONFIG_ARM_64 := y
-CONFIG_ARM_$(XEN_OS) := y
-
-CONFIG_XEN_INSTALL_SUFFIX :=
-
-CFLAGS += #-marm -march= -mcpu= etc
-
-HAS_PL011 := y
-HAS_NS16550 := y
-
-# Use only if calling $(LD) directly.
-LDFLAGS_DIRECT += -EL
-
-CONFIG_LOAD_ADDRESS ?= 0x80000000
-
-IOEMU_CPU_ARCH ?= aarch64
-
-EFI_DIR ?= /usr/lib64/efi
+++ /dev/null
-CONFIG_X86 := y
-CONFIG_X86_32 := y
-CONFIG_X86_$(XEN_OS) := y
-
-CONFIG_HVM := y
-CONFIG_MIGRATE := y
-CONFIG_XCUTILS := y
-
-HAS_MEM_ACCESS := y
-HAS_MEM_PAGING := y
-HAS_MEM_SHARING := y
-
-CFLAGS += -m32 -march=i686
-
-# Use only if calling $(LD) directly.
-LDFLAGS_DIRECT_OpenBSD = _obsd
-LDFLAGS_DIRECT_FreeBSD = _fbsd
-LDFLAGS_DIRECT += -melf_i386$(LDFLAGS_DIRECT_$(XEN_OS))
-
-IOEMU_CPU_ARCH ?= i386
+++ /dev/null
-CONFIG_X86 := y
-CONFIG_X86_64 := y
-CONFIG_X86_$(XEN_OS) := y
-
-CONFIG_COMPAT := y
-CONFIG_HVM := y
-CONFIG_MIGRATE := y
-CONFIG_XCUTILS := y
-
-HAS_MEM_ACCESS := y
-HAS_MEM_PAGING := y
-HAS_MEM_SHARING := y
-
-CONFIG_XEN_INSTALL_SUFFIX := .gz
-
-CFLAGS += -m64
-
-SunOS_LIBDIR = $(SunOS_LIBDIR_x86_64)
-
-EFI_DIR ?= /usr/lib64/efi
-
-# Use only if calling $(LD) directly.
-ifeq ($(XEN_OS),OpenBSD)
-LDFLAGS_DIRECT += -melf_x86_64_obsd
-else
-ifeq ($(XEN_OS),FreeBSD)
-LDFLAGS_DIRECT += -melf_x86_64_fbsd
-else
-LDFLAGS_DIRECT += -melf_x86_64
-endif
-endif
-
-IOEMU_CPU_ARCH ?= x86_64
+++ /dev/null
-/*
- ****************************************************************************
- * (C) 2006 - Grzegorz Milos - Cambridge University
- ****************************************************************************
- *
- * File: console.h
- * Author: Grzegorz Milos
- * Changes:
- *
- * Date: Mar 2006
- *
- * Environment: Xen Minimal OS
- * Description: Console interface.
- *
- * Handles console I/O. Defines printk.
- *
- ****************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <mini-os/types.h>
-#include <mini-os/wait.h>
-#include <mini-os/mm.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/events.h>
-#include <mini-os/os.h>
-#include <mini-os/lib.h>
-#include <mini-os/xenbus.h>
-#include <xen/io/console.h>
-
-
-/* Copies all print output to the Xen emergency console apart
- of standard dom0 handled console */
-#define USE_XEN_CONSOLE
-
-
-/* If console not initialised the printk will be sent to xen serial line
- NOTE: you need to enable verbose in xen/Rules.mk for it to work. */
-static int console_initialised = 0;
-
-__attribute__((weak)) void console_input(char * buf, unsigned len)
-{
- if(len > 0)
- {
- /* Just repeat what's written */
- buf[len] = '\0';
- printk("%s", buf);
-
- if(buf[len-1] == '\r')
- printk("\nNo console input handler.\n");
- }
-}
-
-#ifndef HAVE_LIBC
-void xencons_rx(char *buf, unsigned len, struct pt_regs *regs)
-{
- console_input(buf, len);
-}
-
-void xencons_tx(void)
-{
- /* Do nothing, handled by _rx */
-}
-#endif
-
-
-void console_print(struct consfront_dev *dev, char *data, int length)
-{
- char *curr_char, saved_char;
- char copied_str[length+1];
- char *copied_ptr;
- int part_len;
- int (*ring_send_fn)(struct consfront_dev *dev, const char *data, unsigned length);
-
- if(!console_initialised)
- ring_send_fn = xencons_ring_send_no_notify;
- else
- ring_send_fn = xencons_ring_send;
-
- copied_ptr = copied_str;
- memcpy(copied_ptr, data, length);
- for(curr_char = copied_ptr; curr_char < copied_ptr+length-1; curr_char++)
- {
- if(*curr_char == '\n')
- {
- *curr_char = '\r';
- saved_char = *(curr_char+1);
- *(curr_char+1) = '\n';
- part_len = curr_char - copied_ptr + 2;
- ring_send_fn(dev, copied_ptr, part_len);
- *(curr_char+1) = saved_char;
- copied_ptr = curr_char+1;
- length -= part_len - 1;
- }
- }
-
- if (copied_ptr[length-1] == '\n') {
- copied_ptr[length-1] = '\r';
- copied_ptr[length] = '\n';
- length++;
- }
-
- ring_send_fn(dev, copied_ptr, length);
-}
-
-void print(int direct, const char *fmt, va_list args)
-{
- static char buf[1024];
-
- (void)vsnprintf(buf, sizeof(buf), fmt, args);
-
- if(direct)
- {
- (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
- return;
- } else {
-#ifndef USE_XEN_CONSOLE
- if(!console_initialised)
-#endif
- (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
-
- console_print(NULL, buf, strlen(buf));
- }
-}
-
-void printk(const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- print(0, fmt, args);
- va_end(args);
-}
-
-void xprintk(const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- print(1, fmt, args);
- va_end(args);
-}
-void init_console(void)
-{
- printk("Initialising console ... ");
- xencons_ring_init();
- console_initialised = 1;
- /* This is also required to notify the daemon */
- printk("done.\n");
-}
+++ /dev/null
-
-void console_handle_input(evtchn_port_t port, struct pt_regs *regs, void *data);
+++ /dev/null
-#include <mini-os/types.h>
-#include <mini-os/wait.h>
-#include <mini-os/mm.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/events.h>
-#include <mini-os/os.h>
-#include <mini-os/lib.h>
-#include <mini-os/xenbus.h>
-#include <xen/io/console.h>
-#include <xen/io/protocols.h>
-#include <xen/io/ring.h>
-#include <mini-os/xmalloc.h>
-#include <mini-os/gnttab.h>
-#include "console.h"
-
-void free_consfront(struct consfront_dev *dev)
-{
- char* err = NULL;
- XenbusState state;
-
- char path[strlen(dev->backend) + strlen("/state") + 1];
- char nodename[strlen(dev->nodename) + strlen("/state") + 1];
-
- snprintf(path, sizeof(path), "%s/state", dev->backend);
- snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
-
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
- printk("free_consfront: error changing state to %d: %s\n",
- XenbusStateClosing, err);
- goto close;
- }
- state = xenbus_read_integer(path);
- while (err == NULL && state < XenbusStateClosing)
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- free(err);
-
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
- printk("free_consfront: error changing state to %d: %s\n",
- XenbusStateClosed, err);
- goto close;
- }
-
-close:
- free(err);
- err = xenbus_unwatch_path_token(XBT_NIL, path, path);
- free(err);
-
- mask_evtchn(dev->evtchn);
- unbind_evtchn(dev->evtchn);
- free(dev->backend);
- free(dev->nodename);
-
- gnttab_end_access(dev->ring_ref);
-
- free_page(dev->ring);
- free(dev);
-}
-
-struct consfront_dev *init_consfront(char *_nodename)
-{
- xenbus_transaction_t xbt;
- char* err = NULL;
- char* message=NULL;
- int retry=0;
- char* msg = NULL;
- char nodename[256];
- char path[256];
- static int consfrontends = 3;
- struct consfront_dev *dev;
- int res;
-
- if (!_nodename)
- snprintf(nodename, sizeof(nodename), "device/console/%d", consfrontends);
- else {
- strncpy(nodename, _nodename, sizeof(nodename) - 1);
- nodename[sizeof(nodename) - 1] = 0;
- }
-
- printk("******************* CONSFRONT for %s **********\n\n\n", nodename);
-
- consfrontends++;
- dev = malloc(sizeof(*dev));
- memset(dev, 0, sizeof(*dev));
- dev->nodename = strdup(nodename);
-#ifdef HAVE_LIBC
- dev->fd = -1;
-#endif
-
- snprintf(path, sizeof(path), "%s/backend-id", nodename);
- if ((res = xenbus_read_integer(path)) < 0)
- goto error;
- else
- dev->dom = res;
- evtchn_alloc_unbound(dev->dom, console_handle_input, dev, &dev->evtchn);
-
- dev->ring = (struct xencons_interface *) alloc_page();
- memset(dev->ring, 0, PAGE_SIZE);
- dev->ring_ref = gnttab_grant_access(dev->dom, virt_to_mfn(dev->ring), 0);
-
- dev->events = NULL;
-
-again:
- err = xenbus_transaction_start(&xbt);
- if (err) {
- printk("starting transaction\n");
- free(err);
- }
-
- err = xenbus_printf(xbt, nodename, "ring-ref","%u",
- dev->ring_ref);
- if (err) {
- message = "writing ring-ref";
- goto abort_transaction;
- }
- err = xenbus_printf(xbt, nodename,
- "port", "%u", dev->evtchn);
- if (err) {
- message = "writing event-channel";
- goto abort_transaction;
- }
- err = xenbus_printf(xbt, nodename,
- "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE);
- if (err) {
- message = "writing protocol";
- goto abort_transaction;
- }
-
- snprintf(path, sizeof(path), "%s/state", nodename);
- err = xenbus_switch_state(xbt, path, XenbusStateConnected);
- if (err) {
- message = "switching state";
- goto abort_transaction;
- }
-
-
- err = xenbus_transaction_end(xbt, 0, &retry);
- free(err);
- if (retry) {
- goto again;
- printk("completing transaction\n");
- }
-
- goto done;
-
-abort_transaction:
- free(err);
- err = xenbus_transaction_end(xbt, 1, &retry);
- printk("Abort transaction %s\n", message);
- goto error;
-
-done:
-
- snprintf(path, sizeof(path), "%s/backend", nodename);
- msg = xenbus_read(XBT_NIL, path, &dev->backend);
- if (msg) {
- printk("Error %s when reading the backend path %s\n", msg, path);
- goto error;
- }
-
- printk("backend at %s\n", dev->backend);
-
- {
- XenbusState state;
- char path[strlen(dev->backend) + strlen("/state") + 1];
- snprintf(path, sizeof(path), "%s/state", dev->backend);
-
- xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
- msg = NULL;
- state = xenbus_read_integer(path);
- while (msg == NULL && state < XenbusStateConnected)
- msg = xenbus_wait_for_state_change(path, &state, &dev->events);
- if (msg != NULL || state != XenbusStateConnected) {
- printk("backend not available, state=%d\n", state);
- err = xenbus_unwatch_path_token(XBT_NIL, path, path);
- goto error;
- }
- }
- unmask_evtchn(dev->evtchn);
-
- printk("**************************\n");
-
- return dev;
-
-error:
- free(msg);
- free(err);
- free_consfront(dev);
- return NULL;
-}
-
-void fini_console(struct consfront_dev *dev)
-{
- if (dev) free_consfront(dev);
-}
-
+++ /dev/null
-#include <mini-os/types.h>
-#include <mini-os/wait.h>
-#include <mini-os/mm.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/events.h>
-#include <mini-os/os.h>
-#include <mini-os/lib.h>
-#include <mini-os/xenbus.h>
-#include <xen/io/console.h>
-#include <xen/io/protocols.h>
-#include <xen/io/ring.h>
-#include <mini-os/xmalloc.h>
-#include <mini-os/gnttab.h>
-#include "console.h"
-
-DECLARE_WAIT_QUEUE_HEAD(console_queue);
-
-static inline void notify_daemon(struct consfront_dev *dev)
-{
- /* Use evtchn: this is called early, before irq is set up. */
- if (!dev)
- notify_remote_via_evtchn(start_info.console.domU.evtchn);
- else
- notify_remote_via_evtchn(dev->evtchn);
-}
-
-static inline struct xencons_interface *xencons_interface(void)
-{
- if (start_info.console.domU.evtchn)
- return mfn_to_virt(start_info.console.domU.mfn);
- else
- return NULL;
-}
-
-int xencons_ring_send_no_notify(struct consfront_dev *dev, const char *data, unsigned len)
-{
- int sent = 0;
- struct xencons_interface *intf;
- XENCONS_RING_IDX cons, prod;
-
- if (!dev)
- intf = xencons_interface();
- else
- intf = dev->ring;
- if (!intf)
- return sent;
-
- cons = intf->out_cons;
- prod = intf->out_prod;
- mb();
- BUG_ON((prod - cons) > sizeof(intf->out));
-
- while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
- intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
-
- wmb();
- intf->out_prod = prod;
-
- return sent;
-}
-
-int xencons_ring_send(struct consfront_dev *dev, const char *data, unsigned len)
-{
- int sent;
-
- sent = xencons_ring_send_no_notify(dev, data, len);
- notify_daemon(dev);
-
- return sent;
-}
-
-
-
-void console_handle_input(evtchn_port_t port, struct pt_regs *regs, void *data)
-{
- struct consfront_dev *dev = (struct consfront_dev *) data;
-#ifdef HAVE_LIBC
- int fd = dev ? dev->fd : -1;
-
- if (fd != -1)
- files[fd].read = 1;
-
- wake_up(&console_queue);
-#else
- struct xencons_interface *intf = xencons_interface();
- XENCONS_RING_IDX cons, prod;
-
- cons = intf->in_cons;
- prod = intf->in_prod;
- mb();
- BUG_ON((prod - cons) > sizeof(intf->in));
-
- while (cons != prod) {
- xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1, regs);
- cons++;
- }
-
- mb();
- intf->in_cons = cons;
-
- notify_daemon(dev);
-
- xencons_tx();
-#endif
-}
-
-#ifdef HAVE_LIBC
-int xencons_ring_avail(struct consfront_dev *dev)
-{
- struct xencons_interface *intf;
- XENCONS_RING_IDX cons, prod;
-
- if (!dev)
- intf = xencons_interface();
- else
- intf = dev->ring;
-
- cons = intf->in_cons;
- prod = intf->in_prod;
- mb();
- BUG_ON((prod - cons) > sizeof(intf->in));
-
- return prod - cons;
-}
-
-int xencons_ring_recv(struct consfront_dev *dev, char *data, unsigned len)
-{
- struct xencons_interface *intf;
- XENCONS_RING_IDX cons, prod;
- unsigned filled = 0;
-
- if (!dev)
- intf = xencons_interface();
- else
- intf = dev->ring;
-
- cons = intf->in_cons;
- prod = intf->in_prod;
- mb();
- BUG_ON((prod - cons) > sizeof(intf->in));
-
- while (filled < len && cons + filled != prod) {
- data[filled] = *(intf->in + MASK_XENCONS_IDX(cons + filled, intf->in));
- filled++;
- }
-
- mb();
- intf->in_cons = cons + filled;
-
- notify_daemon(dev);
-
- return filled;
-}
-#endif
-
-struct consfront_dev *xencons_ring_init(void)
-{
- int err;
- struct consfront_dev *dev;
-
- if (!start_info.console.domU.evtchn)
- return 0;
-
- dev = malloc(sizeof(struct consfront_dev));
- memset(dev, 0, sizeof(struct consfront_dev));
- dev->nodename = "device/console";
- dev->dom = 0;
- dev->backend = 0;
- dev->ring_ref = 0;
-
-#ifdef HAVE_LIBC
- dev->fd = -1;
-#endif
- dev->evtchn = start_info.console.domU.evtchn;
- dev->ring = (struct xencons_interface *) mfn_to_virt(start_info.console.domU.mfn);
-
- err = bind_evtchn(dev->evtchn, console_handle_input, dev);
- if (err <= 0) {
- printk("XEN console request chn bind failed %i\n", err);
- free(dev);
- return NULL;
- }
- unmask_evtchn(dev->evtchn);
-
- /* In case we have in-flight data after save/restore... */
- notify_daemon(dev);
-
- return dev;
-}
-
-void xencons_resume(void)
-{
- (void)xencons_ring_init();
-}
-
+++ /dev/null
-/*
- * daytime.c: a simple network service based on lwIP and mini-os
- *
- * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
- */
-
-#include <os.h>
-#include <xmalloc.h>
-#include <console.h>
-#include <netfront.h>
-#include <lwip/api.h>
-
-static char message[29];
-
-void run_server(void *p)
-{
- struct ip_addr listenaddr = { 0 };
- struct netconn *listener;
- struct netconn *session;
- struct timeval tv;
- err_t rc;
-
- start_networking();
-
- if (0) {
- struct ip_addr ipaddr = { htonl(0x0a000001) };
- struct ip_addr netmask = { htonl(0xff000000) };
- struct ip_addr gw = { 0 };
- networking_set_addr(&ipaddr, &netmask, &gw);
- }
-
- tprintk("Opening connection\n");
-
- listener = netconn_new(NETCONN_TCP);
- tprintk("Connection at %p\n", listener);
-
- rc = netconn_bind(listener, &listenaddr, 13);
- if (rc != ERR_OK) {
- tprintk("Failed to bind connection: %i\n", rc);
- return;
- }
-
- rc = netconn_listen(listener);
- if (rc != ERR_OK) {
- tprintk("Failed to listen on connection: %i\n", rc);
- return;
- }
-
- while (1) {
- session = netconn_accept(listener);
- if (session == NULL)
- continue;
-
- gettimeofday(&tv, NULL);
- sprintf(message, "%20lu.%6.6lu\n", tv.tv_sec, tv.tv_usec);
- (void) netconn_write(session, message, strlen(message), NETCONN_COPY);
- (void) netconn_disconnect(session);
- (void) netconn_delete(session);
- }
-}
-
-
-int app_main(start_info_t *si)
-{
- create_thread("server", run_server, NULL);
- return 0;
-}
+++ /dev/null
-# -*- mode: python; -*-
-#============================================================================
-# Python configuration setup for 'xm create'.
-# This script sets the parameters used when a domain is created using 'xm create'.
-# You use a separate script for each domain you want to create, or
-# you can set the parameters for the domain on the xm command line.
-#============================================================================
-
-#----------------------------------------------------------------------------
-# Kernel image file.
-kernel = "mini-os.gz"
-
-# Initial memory allocation (in megabytes) for the new domain.
-memory = 32
-
-# A name for your domain. All domains must have different names.
-name = "Mini-OS"
-
-on_crash = 'destroy'
+++ /dev/null
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
- ****************************************************************************
- *
- * File: events.c
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes: Grzegorz Milos (gm281@cam.ac.uk)
- *
- * Date: Jul 2003, changes Jun 2005
- *
- * Environment: Xen Minimal OS
- * Description: Deals with events recieved on event channels
- *
- ****************************************************************************
- */
-
-#include <mini-os/os.h>
-#include <mini-os/mm.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/events.h>
-#include <mini-os/lib.h>
-#include <xen/xsm/flask_op.h>
-
-#define NR_EVS 1024
-
-/* this represents a event handler. Chaining or sharing is not allowed */
-typedef struct _ev_action_t {
- evtchn_handler_t handler;
- void *data;
- uint32_t count;
-} ev_action_t;
-
-static ev_action_t ev_actions[NR_EVS];
-void default_handler(evtchn_port_t port, struct pt_regs *regs, void *data);
-
-static unsigned long bound_ports[NR_EVS/(8*sizeof(unsigned long))];
-
-void unbind_all_ports(void)
-{
- int i;
- int cpu = 0;
- shared_info_t *s = HYPERVISOR_shared_info;
- vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
-
- for ( i = 0; i < NR_EVS; i++ )
- {
- if ( i == start_info.console.domU.evtchn ||
- i == start_info.store_evtchn)
- continue;
-
- if ( test_and_clear_bit(i, bound_ports) )
- {
- printk("port %d still bound!\n", i);
- unbind_evtchn(i);
- }
- }
- vcpu_info->evtchn_upcall_pending = 0;
- vcpu_info->evtchn_pending_sel = 0;
-}
-
-/*
- * Demux events to different handlers.
- */
-int do_event(evtchn_port_t port, struct pt_regs *regs)
-{
- ev_action_t *action;
-
- clear_evtchn(port);
-
- if ( port >= NR_EVS )
- {
- printk("WARN: do_event(): Port number too large: %d\n", port);
- return 1;
- }
-
- action = &ev_actions[port];
- action->count++;
-
- /* call the handler */
- action->handler(port, regs, action->data);
-
- return 1;
-
-}
-
-evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler,
- void *data)
-{
- if ( ev_actions[port].handler != default_handler )
- printk("WARN: Handler for port %d already registered, replacing\n",
- port);
-
- ev_actions[port].data = data;
- wmb();
- ev_actions[port].handler = handler;
- set_bit(port, bound_ports);
-
- return port;
-}
-
-void unbind_evtchn(evtchn_port_t port )
-{
- struct evtchn_close close;
- int rc;
-
- if ( ev_actions[port].handler == default_handler )
- printk("WARN: No handler for port %d when unbinding\n", port);
- mask_evtchn(port);
- clear_evtchn(port);
-
- ev_actions[port].handler = default_handler;
- wmb();
- ev_actions[port].data = NULL;
- clear_bit(port, bound_ports);
-
- close.port = port;
- rc = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
- if ( rc )
- printk("WARN: close_port %d failed rc=%d. ignored\n", port, rc);
-}
-
-evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
-{
- evtchn_bind_virq_t op;
- int rc;
-
- /* Try to bind the virq to a port */
- op.virq = virq;
- op.vcpu = smp_processor_id();
-
- rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op);
- if (rc != 0)
- {
- printk("Failed to bind virtual IRQ %d with rc=%d\n", virq, rc);
- return -1;
- }
- bind_evtchn(op.port, handler, data);
- return op.port;
-}
-
-evtchn_port_t bind_pirq(uint32_t pirq, int will_share,
- evtchn_handler_t handler, void *data)
-{
- evtchn_bind_pirq_t op;
- int rc;
-
- /* Try to bind the pirq to a port */
- op.pirq = pirq;
- op.flags = will_share ? BIND_PIRQ__WILL_SHARE : 0;
-
- if ( (rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &op)) != 0 )
- {
- printk("Failed to bind physical IRQ %d with rc=%d\n", pirq, rc);
- return -1;
- }
- bind_evtchn(op.port, handler, data);
- return op.port;
-}
-
-/*
- * Initially all events are without a handler and disabled
- */
-void init_events(void)
-{
- int i;
-
- /* initialize event handler */
- for ( i = 0; i < NR_EVS; i++ )
- {
- ev_actions[i].handler = default_handler;
- mask_evtchn(i);
- }
-
- arch_init_events();
-}
-
-void fini_events(void)
-{
- /* Dealloc all events */
- arch_unbind_ports();
- unbind_all_ports();
- arch_fini_events();
-}
-
-void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore)
-{
- printk("[Port %d] - event received\n", port);
-}
-
-/* Create a port available to the pal for exchanging notifications.
- Returns the result of the hypervisor call. */
-
-/* Unfortunate confusion of terminology: the port is unbound as far
- as Xen is concerned, but we automatically bind a handler to it
- from inside mini-os. */
-
-int evtchn_alloc_unbound(domid_t pal, evtchn_handler_t handler,
- void *data, evtchn_port_t *port)
-{
- int rc;
-
- evtchn_alloc_unbound_t op;
- op.dom = DOMID_SELF;
- op.remote_dom = pal;
- rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
- if ( rc )
- {
- printk("ERROR: alloc_unbound failed with rc=%d", rc);
- return rc;
- }
- *port = bind_evtchn(op.port, handler, data);
- return rc;
-}
-
-/* Connect to a port so as to allow the exchange of notifications with
- the pal. Returns the result of the hypervisor call. */
-
-int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port,
- evtchn_handler_t handler, void *data,
- evtchn_port_t *local_port)
-{
- int rc;
- evtchn_port_t port;
- evtchn_bind_interdomain_t op;
- op.remote_dom = pal;
- op.remote_port = remote_port;
- rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, &op);
- if ( rc )
- {
- printk("ERROR: bind_interdomain failed with rc=%d", rc);
- return rc;
- }
- port = op.local_port;
- *local_port = bind_evtchn(port, handler, data);
- return rc;
-}
-
-int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size)
-{
- int rc;
- uint32_t sid;
- struct xen_flask_op op;
- op.cmd = FLASK_GET_PEER_SID;
- op.interface_version = XEN_FLASK_INTERFACE_VERSION;
- op.u.peersid.evtchn = local_port;
- rc = HYPERVISOR_xsm_op(&op);
- if (rc)
- return rc;
- sid = op.u.peersid.sid;
- op.cmd = FLASK_SID_TO_CONTEXT;
- op.u.sid_context.sid = sid;
- op.u.sid_context.size = size;
- set_xen_guest_handle(op.u.sid_context.context, ctx);
- rc = HYPERVISOR_xsm_op(&op);
- return rc;
-}
-
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/*
- * Frame Buffer + Keyboard driver for Mini-OS.
- * Samuel Thibault <samuel.thibault@eu.citrix.com>, 2008
- * Based on blkfront.c.
- */
-
-#include <mini-os/os.h>
-#include <mini-os/xenbus.h>
-#include <mini-os/events.h>
-#include <xen/io/kbdif.h>
-#include <xen/io/fbif.h>
-#include <xen/io/protocols.h>
-#include <mini-os/gnttab.h>
-#include <mini-os/xmalloc.h>
-#include <mini-os/fbfront.h>
-#include <mini-os/lib.h>
-
-DECLARE_WAIT_QUEUE_HEAD(kbdfront_queue);
-
-
-
-
-
-
-struct kbdfront_dev {
- domid_t dom;
-
- struct xenkbd_page *page;
- evtchn_port_t evtchn;
-
- char *nodename;
- char *backend;
-
- xenbus_event_queue events;
-
-#ifdef HAVE_LIBC
- int fd;
-#endif
-};
-
-void kbdfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
-{
-#ifdef HAVE_LIBC
- struct kbdfront_dev *dev = data;
- int fd = dev->fd;
-
- if (fd != -1)
- files[fd].read = 1;
-#endif
- wake_up(&kbdfront_queue);
-}
-
-static void free_kbdfront(struct kbdfront_dev *dev)
-{
- mask_evtchn(dev->evtchn);
-
- free(dev->backend);
-
- free_page(dev->page);
-
- unbind_evtchn(dev->evtchn);
-
- free(dev->nodename);
- free(dev);
-}
-
-struct kbdfront_dev *init_kbdfront(char *_nodename, int abs_pointer)
-{
- xenbus_transaction_t xbt;
- char* err;
- char* message=NULL;
- struct xenkbd_page *s;
- int retry=0;
- char* msg = NULL;
- char* nodename = _nodename ? _nodename : "device/vkbd/0";
- struct kbdfront_dev *dev;
-
- char path[strlen(nodename) + strlen("/backend-id") + 1];
-
- printk("******************* KBDFRONT for %s **********\n\n\n", nodename);
-
- dev = malloc(sizeof(*dev));
- memset(dev, 0, sizeof(*dev));
- dev->nodename = strdup(nodename);
-#ifdef HAVE_LIBC
- dev->fd = -1;
-#endif
-
- snprintf(path, sizeof(path), "%s/backend-id", nodename);
- dev->dom = xenbus_read_integer(path);
- evtchn_alloc_unbound(dev->dom, kbdfront_handler, dev, &dev->evtchn);
-
- dev->page = s = (struct xenkbd_page*) alloc_page();
- memset(s,0,PAGE_SIZE);
-
- dev->events = NULL;
-
- s->in_cons = s->in_prod = 0;
- s->out_cons = s->out_prod = 0;
-
-again:
- err = xenbus_transaction_start(&xbt);
- if (err) {
- printk("starting transaction\n");
- free(err);
- }
-
- err = xenbus_printf(xbt, nodename, "page-ref","%lu", virt_to_mfn(s));
- if (err) {
- message = "writing page-ref";
- goto abort_transaction;
- }
- err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn);
- if (err) {
- message = "writing event-channel";
- goto abort_transaction;
- }
- if (abs_pointer) {
- err = xenbus_printf(xbt, nodename, "request-abs-pointer", "1");
- if (err) {
- message = "writing event-channel";
- goto abort_transaction;
- }
- }
-
- snprintf(path, sizeof(path), "%s/state", nodename);
- err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
- if (err) {
- printk("error writing initialized: %s\n", err);
- free(err);
- }
-
- err = xenbus_transaction_end(xbt, 0, &retry);
- free(err);
- if (retry) {
- goto again;
- printk("completing transaction\n");
- }
-
- goto done;
-
-abort_transaction:
- free(err);
- err = xenbus_transaction_end(xbt, 1, &retry);
- printk("Abort transaction %s\n", message);
- goto error;
-
-done:
-
- snprintf(path, sizeof(path), "%s/backend", nodename);
- msg = xenbus_read(XBT_NIL, path, &dev->backend);
- if (msg) {
- printk("Error %s when reading the backend path %s\n", msg, path);
- goto error;
- }
-
- printk("backend at %s\n", dev->backend);
-
- {
- XenbusState state;
- char path[strlen(dev->backend) + strlen("/state") + 1];
- char frontpath[strlen(nodename) + strlen("/state") + 1];
-
- snprintf(path, sizeof(path), "%s/state", dev->backend);
-
- xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
-
- err = NULL;
- state = xenbus_read_integer(path);
- while (err == NULL && state < XenbusStateConnected)
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- if (state != XenbusStateConnected) {
- printk("backend not available, state=%d\n", state);
- free(err);
- err = xenbus_unwatch_path_token(XBT_NIL, path, path);
- goto error;
- }
-
- printk("%s connected\n", dev->backend);
-
- snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
- if((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
- != NULL) {
- printk("error switching state: %s\n", err);
- free(err);
- err = xenbus_unwatch_path_token(XBT_NIL, path, path);
- goto error;
- }
- }
- unmask_evtchn(dev->evtchn);
-
- printk("************************** KBDFRONT\n");
-
- return dev;
-error:
- free(msg);
- free(err);
- free_kbdfront(dev);
- return NULL;
-}
-
-int kbdfront_receive(struct kbdfront_dev *dev, union xenkbd_in_event *buf, int n)
-{
- struct xenkbd_page *page = dev->page;
- uint32_t prod, cons;
- int i;
-
-#ifdef HAVE_LIBC
- if (dev->fd != -1) {
- files[dev->fd].read = 0;
- mb(); /* Make sure to let the handler set read to 1 before we start looking at the ring */
- }
-#endif
-
- prod = page->in_prod;
-
- if (prod == page->in_cons)
- return 0;
-
- rmb(); /* ensure we see ring contents up to prod */
-
- for (i = 0, cons = page->in_cons; i < n && cons != prod; i++, cons++)
- memcpy(buf + i, &XENKBD_IN_RING_REF(page, cons), sizeof(*buf));
-
- mb(); /* ensure we got ring contents */
- page->in_cons = cons;
- notify_remote_via_evtchn(dev->evtchn);
-
-#ifdef HAVE_LIBC
- if (cons != prod && dev->fd != -1)
- /* still some events to read */
- files[dev->fd].read = 1;
-#endif
-
- return i;
-}
-
-
-void shutdown_kbdfront(struct kbdfront_dev *dev)
-{
- char* err = NULL, *err2;
- XenbusState state;
-
- char path[strlen(dev->backend) + strlen("/state") + 1];
- char nodename[strlen(dev->nodename) + strlen("/request-abs-pointer") + 1];
-
- printk("close kbd: backend at %s\n",dev->backend);
-
- snprintf(path, sizeof(path), "%s/state", dev->backend);
- snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
- printk("shutdown_kbdfront: error changing state to %d: %s\n",
- XenbusStateClosing, err);
- goto close_kbdfront;
- }
- state = xenbus_read_integer(path);
- while (err == NULL && state < XenbusStateClosing)
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- free(err);
-
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
- printk("shutdown_kbdfront: error changing state to %d: %s\n",
- XenbusStateClosed, err);
- goto close_kbdfront;
- }
- state = xenbus_read_integer(path);
- while (state < XenbusStateClosed) {
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- free(err);
- }
-
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
- printk("shutdown_kbdfront: error changing state to %d: %s\n",
- XenbusStateInitialising, err);
- goto close_kbdfront;
- }
- state = xenbus_read_integer(path);
- while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
-
-close_kbdfront:
- free(err);
- err2 = xenbus_unwatch_path_token(XBT_NIL, path, path);
- free(err2);
-
- snprintf(nodename, sizeof(nodename), "%s/page-ref", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
- snprintf(nodename, sizeof(nodename), "%s/event-channel", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
- snprintf(nodename, sizeof(nodename), "%s/request-abs-pointer", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
-
- if (!err)
- free_kbdfront(dev);
-}
-
-#ifdef HAVE_LIBC
-int kbdfront_open(struct kbdfront_dev *dev)
-{
- dev->fd = alloc_fd(FTYPE_KBD);
- printk("kbd_open(%s) -> %d\n", dev->nodename, dev->fd);
- files[dev->fd].kbd.dev = dev;
- return dev->fd;
-}
-#endif
-
-
-
-
-
-DECLARE_WAIT_QUEUE_HEAD(fbfront_queue);
-
-
-
-
-
-
-struct fbfront_dev {
- domid_t dom;
-
- struct xenfb_page *page;
- evtchn_port_t evtchn;
-
- char *nodename;
- char *backend;
- int request_update;
-
- int width;
- int height;
- int depth;
- int stride;
- int mem_length;
- int offset;
-
- xenbus_event_queue events;
-
-#ifdef HAVE_LIBC
- int fd;
-#endif
-};
-
-void fbfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
-{
-#ifdef HAVE_LIBC
- struct fbfront_dev *dev = data;
- int fd = dev->fd;
-
- if (fd != -1)
- files[fd].read = 1;
-#endif
- wake_up(&fbfront_queue);
-}
-
-static void free_fbfront(struct fbfront_dev *dev)
-{
- mask_evtchn(dev->evtchn);
-
- free(dev->backend);
-
- free_page(dev->page);
-
- unbind_evtchn(dev->evtchn);
-
- free(dev->nodename);
- free(dev);
-}
-
-int fbfront_receive(struct fbfront_dev *dev, union xenfb_in_event *buf, int n)
-{
- struct xenfb_page *page = dev->page;
- uint32_t prod, cons;
- int i;
-
-#ifdef HAVE_LIBC
- if (dev->fd != -1) {
- files[dev->fd].read = 0;
- mb(); /* Make sure to let the handler set read to 1 before we start looking at the ring */
- }
-#endif
-
- prod = page->in_prod;
-
- if (prod == page->in_cons)
- return 0;
-
- rmb(); /* ensure we see ring contents up to prod */
-
- for (i = 0, cons = page->in_cons; i < n && cons != prod; i++, cons++)
- memcpy(buf + i, &XENFB_IN_RING_REF(page, cons), sizeof(*buf));
-
- mb(); /* ensure we got ring contents */
- page->in_cons = cons;
- notify_remote_via_evtchn(dev->evtchn);
-
-#ifdef HAVE_LIBC
- if (cons != prod && dev->fd != -1)
- /* still some events to read */
- files[dev->fd].read = 1;
-#endif
-
- return i;
-}
-
-struct fbfront_dev *init_fbfront(char *_nodename, unsigned long *mfns, int width, int height, int depth, int stride, int n)
-{
- xenbus_transaction_t xbt;
- char* err;
- char* message=NULL;
- struct xenfb_page *s;
- int retry=0;
- char* msg=NULL;
- int i, j;
- struct fbfront_dev *dev;
- int max_pd;
- unsigned long mapped;
- char* nodename = _nodename ? _nodename : "device/vfb/0";
-
- char path[strlen(nodename) + strlen("/backend-id") + 1];
-
- printk("******************* FBFRONT for %s **********\n\n\n", nodename);
-
- dev = malloc(sizeof(*dev));
- memset(dev, 0, sizeof(*dev));
- dev->nodename = strdup(nodename);
-#ifdef HAVE_LIBC
- dev->fd = -1;
-#endif
-
- snprintf(path, sizeof(path), "%s/backend-id", nodename);
- dev->dom = xenbus_read_integer(path);
- evtchn_alloc_unbound(dev->dom, fbfront_handler, dev, &dev->evtchn);
-
- dev->page = s = (struct xenfb_page*) alloc_page();
- memset(s,0,PAGE_SIZE);
-
- s->in_cons = s->in_prod = 0;
- s->out_cons = s->out_prod = 0;
- dev->width = s->width = width;
- dev->height = s->height = height;
- dev->depth = s->depth = depth;
- dev->stride = s->line_length = stride;
- dev->mem_length = s->mem_length = n * PAGE_SIZE;
- dev->offset = 0;
- dev->events = NULL;
-
- max_pd = sizeof(s->pd) / sizeof(s->pd[0]);
- mapped = 0;
-
- for (i = 0; mapped < n && i < max_pd; i++) {
- unsigned long *pd = (unsigned long *) alloc_page();
- for (j = 0; mapped < n && j < PAGE_SIZE / sizeof(unsigned long); j++)
- pd[j] = mfns[mapped++];
- for ( ; j < PAGE_SIZE / sizeof(unsigned long); j++)
- pd[j] = 0;
- s->pd[i] = virt_to_mfn(pd);
- }
- for ( ; i < max_pd; i++)
- s->pd[i] = 0;
-
-
-again:
- err = xenbus_transaction_start(&xbt);
- if (err) {
- printk("starting transaction\n");
- free(err);
- }
-
- err = xenbus_printf(xbt, nodename, "page-ref","%lu", virt_to_mfn(s));
- if (err) {
- message = "writing page-ref";
- goto abort_transaction;
- }
- err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn);
- if (err) {
- message = "writing event-channel";
- goto abort_transaction;
- }
- err = xenbus_printf(xbt, nodename, "protocol", "%s",
- XEN_IO_PROTO_ABI_NATIVE);
- if (err) {
- message = "writing event-channel";
- goto abort_transaction;
- }
- err = xenbus_printf(xbt, nodename, "feature-update", "1");
- if (err) {
- message = "writing event-channel";
- goto abort_transaction;
- }
-
- snprintf(path, sizeof(path), "%s/state", nodename);
- err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
- if (err) {
- message = "switching state";
- goto abort_transaction;
- }
-
- err = xenbus_transaction_end(xbt, 0, &retry);
- free(err);
- if (retry) {
- goto again;
- printk("completing transaction\n");
- }
-
- goto done;
-
-abort_transaction:
- free(err);
- err = xenbus_transaction_end(xbt, 1, &retry);
- printk("Abort transaction %s\n", message);
- goto error;
-
-done:
-
- snprintf(path, sizeof(path), "%s/backend", nodename);
- msg = xenbus_read(XBT_NIL, path, &dev->backend);
- if (msg) {
- printk("Error %s when reading the backend path %s\n", msg, path);
- goto error;
- }
-
- printk("backend at %s\n", dev->backend);
-
- {
- XenbusState state;
- char path[strlen(dev->backend) + strlen("/request-update") + 1];
- char frontpath[strlen(nodename) + strlen("/state") + 1];
-
- snprintf(path, sizeof(path), "%s/state", dev->backend);
-
- xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
-
- err = NULL;
- state = xenbus_read_integer(path);
- while (err == NULL && state < XenbusStateConnected)
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- if (state != XenbusStateConnected) {
- printk("backend not available, state=%d\n", state);
- free(err);
- err = xenbus_unwatch_path_token(XBT_NIL, path, path);
- goto error;
- }
-
- printk("%s connected\n", dev->backend);
-
- snprintf(path, sizeof(path), "%s/request-update", dev->backend);
- dev->request_update = xenbus_read_integer(path);
-
- snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
- if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
- != NULL) {
- printk("error switching state: %s\n", err);
- free(err);
- err = xenbus_unwatch_path_token(XBT_NIL, path, path);
- goto error;
- }
- }
- unmask_evtchn(dev->evtchn);
-
- printk("************************** FBFRONT\n");
-
- return dev;
-
-error:
- free(msg);
- free(err);
- free_fbfront(dev);
- return NULL;
-}
-
-static void fbfront_out_event(struct fbfront_dev *dev, union xenfb_out_event *event)
-{
- struct xenfb_page *page = dev->page;
- uint32_t prod;
- DEFINE_WAIT(w);
-
- add_waiter(w, fbfront_queue);
- while (page->out_prod - page->out_cons == XENFB_OUT_RING_LEN)
- schedule();
- remove_waiter(w, fbfront_queue);
-
- prod = page->out_prod;
- mb(); /* ensure ring space available */
- XENFB_OUT_RING_REF(page, prod) = *event;
- wmb(); /* ensure ring contents visible */
- page->out_prod = prod + 1;
- notify_remote_via_evtchn(dev->evtchn);
-}
-
-void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int height)
-{
- struct xenfb_update update;
-
- if (dev->request_update <= 0)
- return;
-
- if (x < 0) {
- width += x;
- x = 0;
- }
- if (x + width > dev->width)
- width = dev->width - x;
-
- if (y < 0) {
- height += y;
- y = 0;
- }
- if (y + height > dev->height)
- height = dev->height - y;
-
- if (width <= 0 || height <= 0)
- return;
-
- update.type = XENFB_TYPE_UPDATE;
- update.x = x;
- update.y = y;
- update.width = width;
- update.height = height;
- fbfront_out_event(dev, (union xenfb_out_event *) &update);
-}
-
-void fbfront_resize(struct fbfront_dev *dev, int width, int height, int stride, int depth, int offset)
-{
- struct xenfb_resize resize;
-
- resize.type = XENFB_TYPE_RESIZE;
- dev->width = resize.width = width;
- dev->height = resize.height = height;
- dev->stride = resize.stride = stride;
- dev->depth = resize.depth = depth;
- dev->offset = resize.offset = offset;
- fbfront_out_event(dev, (union xenfb_out_event *) &resize);
-}
-
-void shutdown_fbfront(struct fbfront_dev *dev)
-{
- char* err = NULL, *err2;
- XenbusState state;
-
- char path[strlen(dev->backend) + strlen("/state") + 1];
- char nodename[strlen(dev->nodename) + strlen("/feature-update") + 1];
-
- printk("close fb: backend at %s\n",dev->backend);
-
- snprintf(path, sizeof(path), "%s/state", dev->backend);
- snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
- printk("shutdown_fbfront: error changing state to %d: %s\n",
- XenbusStateClosing, err);
- goto close_fbfront;
- }
- state = xenbus_read_integer(path);
- while (err == NULL && state < XenbusStateClosing)
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- free(err);
-
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
- printk("shutdown_fbfront: error changing state to %d: %s\n",
- XenbusStateClosed, err);
- goto close_fbfront;
- }
- state = xenbus_read_integer(path);
- if (state < XenbusStateClosed) {
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- free(err);
- }
-
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
- printk("shutdown_fbfront: error changing state to %d: %s\n",
- XenbusStateInitialising, err);
- goto close_fbfront;
- }
- state = xenbus_read_integer(path);
- while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
-
-close_fbfront:
- free(err);
- err2 = xenbus_unwatch_path_token(XBT_NIL, path, path);
- free(err2);
-
- snprintf(nodename, sizeof(nodename), "%s/page-ref", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
- snprintf(nodename, sizeof(nodename), "%s/event-channel", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
- snprintf(nodename, sizeof(nodename), "%s/protocol", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
- snprintf(nodename, sizeof(nodename), "%s/feature-update", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
-
- if (!err)
- free_fbfront(dev);
-}
-
-#ifdef HAVE_LIBC
-int fbfront_open(struct fbfront_dev *dev)
-{
- dev->fd = alloc_fd(FTYPE_FB);
- printk("fb_open(%s) -> %d\n", dev->nodename, dev->fd);
- files[dev->fd].fb.dev = dev;
- return dev->fd;
-}
-#endif
-
+++ /dev/null
-/*
- * Manages grant mappings from other domains.
- *
- * Diego Ongaro <diego.ongaro@citrix.com>, July 2008
- *
- * Files of type FTYPE_GNTMAP contain a gntmap, which is an array of
- * (host address, grant handle) pairs. Grant handles come from a hypervisor map
- * operation and are needed for the corresponding unmap.
- *
- * This is a rather naive implementation in terms of performance. If we start
- * using it frequently, there's definitely some low-hanging fruit here.
- *
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <mini-os/os.h>
-#include <mini-os/lib.h>
-#include <mini-os/xmalloc.h>
-#include <errno.h>
-#include <xen/grant_table.h>
-#include <inttypes.h>
-#include <mini-os/gntmap.h>
-
-//#define GNTMAP_DEBUG
-#ifdef GNTMAP_DEBUG
-#define DEBUG(_f, _a...) \
- printk("MINI_OS(gntmap.c:%d): %s" _f "\n", __LINE__, __func__, ## _a)
-#else
-#define DEBUG(_f, _a...) ((void)0)
-#endif
-
-
-#define DEFAULT_MAX_GRANTS 128
-
-struct gntmap_entry {
- unsigned long host_addr;
- grant_handle_t handle;
-};
-
-static inline int
-gntmap_entry_used(struct gntmap_entry *entry)
-{
- return entry->host_addr != 0;
-}
-
-static struct gntmap_entry*
-gntmap_find_free_entry(struct gntmap *map)
-{
- int i;
-
- for (i = 0; i < map->nentries; i++) {
- if (!gntmap_entry_used(&map->entries[i]))
- return &map->entries[i];
- }
-
- DEBUG("(map=%p): all %d entries full",
- map, map->nentries);
- return NULL;
-}
-
-static struct gntmap_entry*
-gntmap_find_entry(struct gntmap *map, unsigned long addr)
-{
- int i;
-
- for (i = 0; i < map->nentries; i++) {
- if (map->entries[i].host_addr == addr)
- return &map->entries[i];
- }
- return NULL;
-}
-
-int
-gntmap_set_max_grants(struct gntmap *map, int count)
-{
- DEBUG("(map=%p, count=%d)", map, count);
-
- if (map->nentries != 0)
- return -EBUSY;
-
- map->entries = xmalloc_array(struct gntmap_entry, count);
- if (map->entries == NULL)
- return -ENOMEM;
-
- memset(map->entries, 0, sizeof(struct gntmap_entry) * count);
- map->nentries = count;
- return 0;
-}
-
-static int
-_gntmap_map_grant_ref(struct gntmap_entry *entry,
- unsigned long host_addr,
- uint32_t domid,
- uint32_t ref,
- int writable)
-{
- struct gnttab_map_grant_ref op;
- int rc;
-
- op.ref = (grant_ref_t) ref;
- op.dom = (domid_t) domid;
- op.host_addr = (uint64_t) host_addr;
- op.flags = GNTMAP_host_map;
- if (!writable)
- op.flags |= GNTMAP_readonly;
-
- rc = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
- if (rc != 0 || op.status != GNTST_okay) {
- printk("GNTTABOP_map_grant_ref failed: "
- "returned %d, status %" PRId16 "\n",
- rc, op.status);
- return rc != 0 ? rc : op.status;
- }
-
- entry->host_addr = host_addr;
- entry->handle = op.handle;
- return 0;
-}
-
-static int
-_gntmap_unmap_grant_ref(struct gntmap_entry *entry)
-{
- struct gnttab_unmap_grant_ref op;
- int rc;
-
- op.host_addr = (uint64_t) entry->host_addr;
- op.dev_bus_addr = 0;
- op.handle = entry->handle;
-
- rc = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
- if (rc != 0 || op.status != GNTST_okay) {
- printk("GNTTABOP_unmap_grant_ref failed: "
- "returned %d, status %" PRId16 "\n",
- rc, op.status);
- return rc != 0 ? rc : op.status;
- }
-
- entry->host_addr = 0;
- return 0;
-}
-
-int
-gntmap_munmap(struct gntmap *map, unsigned long start_address, int count)
-{
- int i, rc;
- struct gntmap_entry *ent;
-
- DEBUG("(map=%p, start_address=%lx, count=%d)",
- map, start_address, count);
-
- for (i = 0; i < count; i++) {
- ent = gntmap_find_entry(map, start_address + PAGE_SIZE * i);
- if (ent == NULL) {
- printk("gntmap: tried to munmap unknown page\n");
- return -EINVAL;
- }
-
- rc = _gntmap_unmap_grant_ref(ent);
- if (rc != 0)
- return rc;
- }
-
- return 0;
-}
-
-void*
-gntmap_map_grant_refs(struct gntmap *map,
- uint32_t count,
- uint32_t *domids,
- int domids_stride,
- uint32_t *refs,
- int writable)
-{
- unsigned long addr;
- struct gntmap_entry *ent;
- int i;
-
- DEBUG("(map=%p, count=%" PRIu32 ", "
- "domids=%p [%" PRIu32 "...], domids_stride=%d, "
- "refs=%p [%" PRIu32 "...], writable=%d)",
- map, count,
- domids, domids == NULL ? 0 : domids[0], domids_stride,
- refs, refs == NULL ? 0 : refs[0], writable);
-
- (void) gntmap_set_max_grants(map, DEFAULT_MAX_GRANTS);
-
- addr = allocate_ondemand((unsigned long) count, 1);
- if (addr == 0)
- return NULL;
-
- for (i = 0; i < count; i++) {
- ent = gntmap_find_free_entry(map);
- if (ent == NULL ||
- _gntmap_map_grant_ref(ent,
- addr + PAGE_SIZE * i,
- domids[i * domids_stride],
- refs[i],
- writable) != 0) {
-
- (void) gntmap_munmap(map, addr, i);
- return NULL;
- }
- }
-
- return (void*) addr;
-}
-
-void
-gntmap_init(struct gntmap *map)
-{
- DEBUG("(map=%p)", map);
- map->nentries = 0;
- map->entries = NULL;
-}
-
-void
-gntmap_fini(struct gntmap *map)
-{
- struct gntmap_entry *ent;
- int i;
-
- DEBUG("(map=%p)", map);
-
- for (i = 0; i < map->nentries; i++) {
- ent = &map->entries[i];
- if (gntmap_entry_used(ent))
- (void) _gntmap_unmap_grant_ref(ent);
- }
-
- xfree(map->entries);
- map->entries = NULL;
- map->nentries = 0;
-}
+++ /dev/null
-/*
- ****************************************************************************
- * (C) 2006 - Cambridge University
- ****************************************************************************
- *
- * File: gnttab.c
- * Author: Steven Smith (sos22@cam.ac.uk)
- * Changes: Grzegorz Milos (gm281@cam.ac.uk)
- *
- * Date: July 2006
- *
- * Environment: Xen Minimal OS
- * Description: Simple grant tables implementation. About as stupid as it's
- * possible to be and still work.
- *
- ****************************************************************************
- */
-#include <mini-os/os.h>
-#include <mini-os/mm.h>
-#include <mini-os/gnttab.h>
-#include <mini-os/semaphore.h>
-
-#define NR_RESERVED_ENTRIES 8
-
-/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
-#define NR_GRANT_FRAMES 4
-#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
-
-static grant_entry_t *gnttab_table;
-static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
-#ifdef GNT_DEBUG
-static char inuse[NR_GRANT_ENTRIES];
-#endif
-static __DECLARE_SEMAPHORE_GENERIC(gnttab_sem, 0);
-
-static void
-put_free_entry(grant_ref_t ref)
-{
- unsigned long flags;
- local_irq_save(flags);
-#ifdef GNT_DEBUG
- BUG_ON(!inuse[ref]);
- inuse[ref] = 0;
-#endif
- gnttab_list[ref] = gnttab_list[0];
- gnttab_list[0] = ref;
- local_irq_restore(flags);
- up(&gnttab_sem);
-}
-
-static grant_ref_t
-get_free_entry(void)
-{
- unsigned int ref;
- unsigned long flags;
- down(&gnttab_sem);
- local_irq_save(flags);
- ref = gnttab_list[0];
- BUG_ON(ref < NR_RESERVED_ENTRIES || ref >= NR_GRANT_ENTRIES);
- gnttab_list[0] = gnttab_list[ref];
-#ifdef GNT_DEBUG
- BUG_ON(inuse[ref]);
- inuse[ref] = 1;
-#endif
- local_irq_restore(flags);
- return ref;
-}
-
-grant_ref_t
-gnttab_grant_access(domid_t domid, unsigned long frame, int readonly)
-{
- grant_ref_t ref;
-
- ref = get_free_entry();
- gnttab_table[ref].frame = frame;
- gnttab_table[ref].domid = domid;
- wmb();
- readonly *= GTF_readonly;
- gnttab_table[ref].flags = GTF_permit_access | readonly;
-
- return ref;
-}
-
-grant_ref_t
-gnttab_grant_transfer(domid_t domid, unsigned long pfn)
-{
- grant_ref_t ref;
-
- ref = get_free_entry();
- gnttab_table[ref].frame = pfn;
- gnttab_table[ref].domid = domid;
- wmb();
- gnttab_table[ref].flags = GTF_accept_transfer;
-
- return ref;
-}
-
-int
-gnttab_end_access(grant_ref_t ref)
-{
- uint16_t flags, nflags;
-
- BUG_ON(ref >= NR_GRANT_ENTRIES || ref < NR_RESERVED_ENTRIES);
-
- nflags = gnttab_table[ref].flags;
- do {
- if ((flags = nflags) & (GTF_reading|GTF_writing)) {
- printk("WARNING: g.e. still in use! (%x)\n", flags);
- return 0;
- }
- } while ((nflags = synch_cmpxchg(&gnttab_table[ref].flags, flags, 0)) !=
- flags);
-
- put_free_entry(ref);
- return 1;
-}
-
-unsigned long
-gnttab_end_transfer(grant_ref_t ref)
-{
- unsigned long frame;
- uint16_t flags;
-
- BUG_ON(ref >= NR_GRANT_ENTRIES || ref < NR_RESERVED_ENTRIES);
-
- while (!((flags = gnttab_table[ref].flags) & GTF_transfer_committed)) {
- if (synch_cmpxchg(&gnttab_table[ref].flags, flags, 0) == flags) {
- printk("Release unused transfer grant.\n");
- put_free_entry(ref);
- return 0;
- }
- }
-
- /* If a transfer is in progress then wait until it is completed. */
- while (!(flags & GTF_transfer_completed)) {
- flags = gnttab_table[ref].flags;
- }
-
- /* Read the frame number /after/ reading completion status. */
- rmb();
- frame = gnttab_table[ref].frame;
-
- put_free_entry(ref);
-
- return frame;
-}
-
-grant_ref_t
-gnttab_alloc_and_grant(void **map)
-{
- unsigned long mfn;
- grant_ref_t gref;
-
- *map = (void *)alloc_page();
- mfn = virt_to_mfn(*map);
- gref = gnttab_grant_access(0, mfn, 0);
- return gref;
-}
-
-static const char * const gnttabop_error_msgs[] = GNTTABOP_error_msgs;
-
-const char *
-gnttabop_error(int16_t status)
-{
- status = -status;
- if (status < 0 || status >= ARRAY_SIZE(gnttabop_error_msgs))
- return "bad status";
- else
- return gnttabop_error_msgs[status];
-}
-
-void
-init_gnttab(void)
-{
- int i;
-
-#ifdef GNT_DEBUG
- memset(inuse, 1, sizeof(inuse));
-#endif
- for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
- put_free_entry(i);
-
- gnttab_table = arch_init_gnttab(NR_GRANT_FRAMES);
- printk("gnttab_table mapped at %p.\n", gnttab_table);
-}
-
-void
-fini_gnttab(void)
-{
- struct gnttab_setup_table setup;
-
- setup.dom = DOMID_SELF;
- setup.nr_frames = 0;
-
- HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
-}
+++ /dev/null
-/******************************************************************************
- * hypervisor.c
- *
- * Communication to/from hypervisor.
- *
- * Copyright (c) 2002-2003, K A Fraser
- * Copyright (c) 2005, Grzegorz Milos, gm281@cam.ac.uk,Intel Research Cambridge
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <mini-os/os.h>
-#include <mini-os/lib.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/events.h>
-
-#define active_evtchns(cpu,sh,idx) \
- ((sh)->evtchn_pending[idx] & \
- ~(sh)->evtchn_mask[idx])
-
-int in_callback;
-
-void do_hypervisor_callback(struct pt_regs *regs)
-{
- unsigned long l1, l2, l1i, l2i;
- unsigned int port;
- int cpu = 0;
- shared_info_t *s = HYPERVISOR_shared_info;
- vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
-
- in_callback = 1;
-
- vcpu_info->evtchn_upcall_pending = 0;
- /* NB x86. No need for a barrier here -- XCHG is a barrier on x86. */
-#if !defined(__i386__) && !defined(__x86_64__)
- /* Clear master flag /before/ clearing selector flag. */
- wmb();
-#endif
- l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
- while ( l1 != 0 )
- {
- l1i = __ffs(l1);
- l1 &= ~(1UL << l1i);
-
- while ( (l2 = active_evtchns(cpu, s, l1i)) != 0 )
- {
- l2i = __ffs(l2);
- l2 &= ~(1UL << l2i);
-
- port = (l1i * (sizeof(unsigned long) * 8)) + l2i;
- do_event(port, regs);
- }
- }
-
- in_callback = 0;
-}
-
-void force_evtchn_callback(void)
-{
-#ifdef XEN_HAVE_PV_UPCALL_MASK
- int save;
-#endif
- vcpu_info_t *vcpu;
- vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
-#ifdef XEN_HAVE_PV_UPCALL_MASK
- save = vcpu->evtchn_upcall_mask;
-#endif
-
- while (vcpu->evtchn_upcall_pending) {
-#ifdef XEN_HAVE_PV_UPCALL_MASK
- vcpu->evtchn_upcall_mask = 1;
-#endif
- barrier();
- do_hypervisor_callback(NULL);
- barrier();
-#ifdef XEN_HAVE_PV_UPCALL_MASK
- vcpu->evtchn_upcall_mask = save;
- barrier();
-#endif
- };
-}
-
-inline void mask_evtchn(uint32_t port)
-{
- shared_info_t *s = HYPERVISOR_shared_info;
- synch_set_bit(port, &s->evtchn_mask[0]);
-}
-
-inline void unmask_evtchn(uint32_t port)
-{
- shared_info_t *s = HYPERVISOR_shared_info;
- vcpu_info_t *vcpu_info = &s->vcpu_info[smp_processor_id()];
-
- synch_clear_bit(port, &s->evtchn_mask[0]);
-
- /*
- * The following is basically the equivalent of 'hw_resend_irq'. Just like
- * a real IO-APIC we 'lose the interrupt edge' if the channel is masked.
- */
- if ( synch_test_bit (port, &s->evtchn_pending[0]) &&
- !synch_test_and_set_bit(port / (sizeof(unsigned long) * 8),
- &vcpu_info->evtchn_pending_sel) )
- {
- vcpu_info->evtchn_upcall_pending = 1;
-#ifdef XEN_HAVE_PV_UPCALL_MASK
- if ( !vcpu_info->evtchn_upcall_mask )
-#endif
- force_evtchn_callback();
- }
-}
-
-inline void clear_evtchn(uint32_t port)
-{
- shared_info_t *s = HYPERVISOR_shared_info;
- synch_clear_bit(port, &s->evtchn_pending[0]);
-}
+++ /dev/null
-/*
- * lwip/arch/cc.h
- *
- * Compiler-specific types and macros for lwIP running on mini-os
- *
- * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
- */
-
-#ifndef __LWIP_ARCH_CC_H__
-#define __LWIP_ARCH_CC_H__
-
-/* Typedefs for the types used by lwip - */
-#include <mini-os/os.h>
-#include <mini-os/types.h>
-#include <time.h>
-typedef uint8_t u8_t;
-typedef int8_t s8_t;
-typedef uint16_t u16_t;
-typedef int16_t s16_t;
-typedef uint32_t u32_t;
-typedef int32_t s32_t;
-typedef uint64_t u64_t;
-typedef int64_t s64_t;
-typedef uintptr_t mem_ptr_t;
-
-typedef uint16_t u_short;
-
-/* Compiler hints for packing lwip's structures - */
-#define PACK_STRUCT_FIELD(_x) _x
-#define PACK_STRUCT_STRUCT __attribute__ ((packed))
-#define PACK_STRUCT_BEGIN
-#define PACK_STRUCT_END
-
-/* Platform specific diagnostic output - */
-
-extern void lwip_printk(char *fmt, ...);
-#define LWIP_PLATFORM_DIAG(_x) do { lwip_printk _x ; } while (0)
-
-extern void lwip_die(char *fmt, ...);
-#define LWIP_PLATFORM_ASSERT(_x) do { lwip_die(_x); } while(0)
-
-/* "lightweight" synchronization mechanisms - */
-/* SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable. */
-/* SYS_ARCH_PROTECT(x) - enter protection mode. */
-/* SYS_ARCH_UNPROTECT(x) - leave protection mode. */
-
-/* If the compiler does not provide memset() this file must include a */
-/* definition of it, or include a file which defines it. */
-#include <mini-os/lib.h>
-
-/* This file must either include a system-local <errno.h> which defines */
-/* the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO */
-/* to make lwip/arch.h define the codes which are used throughout. */
-#include <errno.h>
-
-/* Not required by the docs, but needed for network-order calculations */
-#ifdef HAVE_LIBC
-#include <machine/endian.h>
-#ifndef BIG_ENDIAN
-#error endian.h does not define byte order
-#endif
-#else
-#include <endian.h>
-#endif
-
-#include <inttypes.h>
-#define S16_F PRIi16
-#define U16_F PRIu16
-#define X16_F PRIx16
-#define S32_F PRIi32
-#define U32_F PRIu32
-#define X32_F PRIx32
-
-#if 0
-#ifndef DBG_ON
-#define DBG_ON LWIP_DBG_ON
-#endif
-#define LWIP_DEBUG DBG_ON
-//#define IP_DEBUG DBG_ON
-#define TCP_DEBUG DBG_ON
-#define TCP_INPUT_DEBUG DBG_ON
-#define TCP_QLEN_DEBUG DBG_ON
-#define TCPIP_DEBUG DBG_ON
-#define DBG_TYPES_ON DBG_ON
-#endif
-
-#endif /* __LWIP_ARCH_CC_H__ */
+++ /dev/null
-/*
- * lwip/arch/perf.h
- *
- * Arch-specific performance measurement for lwIP running on mini-os
- *
- * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
- */
-
-#ifndef __LWIP_ARCH_PERF_H__
-#define __LWIP_ARCH_PERF_H__
-
-#define PERF_START do { } while(0)
-#define PERF_STOP(_x) do { (void)(_x); } while (0)
-
-#endif /* __LWIP_ARCH_PERF_H__ */
+++ /dev/null
-/*
- * lwip/arch/sys_arch.h
- *
- * Arch-specific semaphores and mailboxes for lwIP running on mini-os
- *
- * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
- */
-
-#ifndef __LWIP_ARCH_SYS_ARCH_H__
-#define __LWIP_ARCH_SYS_ARCH_H__
-
-#include <mini-os/os.h>
-#include <mini-os/xmalloc.h>
-#include <mini-os/semaphore.h>
-
-typedef struct semaphore *sys_sem_t;
-#define SYS_SEM_NULL ((sys_sem_t) NULL)
-
-struct mbox {
- int count;
- void **messages;
- struct semaphore read_sem;
- struct semaphore write_sem;
- int writer;
- int reader;
-};
-
-typedef struct mbox *sys_mbox_t;
-#define SYS_MBOX_NULL ((sys_mbox_t) 0)
-
-typedef struct thread *sys_thread_t;
-
-typedef unsigned long sys_prot_t;
-
-#endif /*__LWIP_ARCH_SYS_ARCH_H__ */
+++ /dev/null
-#ifndef ARCH_ENDIAN_H
-#error "Do not include arch_endian by itself, include endian.h"
-#else
-
-#define __BYTE_ORDER __LITTLE_ENDIAN
-
-#endif
+++ /dev/null
-#ifndef __ARCH_LIMITS_H__
-#define __ARCH_LIMITS_H__
-
-#include <mm.h>
-
-#define __STACK_SIZE_PAGE_ORDER 2
-#define __STACK_SIZE (4 * PAGE_SIZE)
-
-#endif
+++ /dev/null
-#ifndef _ARCH_MM_H_
-#define _ARCH_MM_H_
-
-typedef uint64_t paddr_t;
-
-extern char _text, _etext, _erodata, _edata, _end, __bss_start;
-extern int _boot_stack[];
-extern int _boot_stack_end[];
-extern uint32_t physical_address_offset; /* Add this to a virtual address to get the physical address (wraps at 4GB) */
-
-#define PAGE_SHIFT 12
-#define PAGE_SIZE (1 << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
-
-#define L1_PAGETABLE_SHIFT 12
-
-#define to_phys(x) (((paddr_t)(x)+physical_address_offset) & 0xffffffff)
-#define to_virt(x) ((void *)(((x)-physical_address_offset) & 0xffffffff))
-
-#define PFN_UP(x) (unsigned long)(((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT)
-#define PFN_DOWN(x) (unsigned long)((x) >> L1_PAGETABLE_SHIFT)
-#define PFN_PHYS(x) ((uint64_t)(x) << L1_PAGETABLE_SHIFT)
-#define PHYS_PFN(x) (unsigned long)((x) >> L1_PAGETABLE_SHIFT)
-
-#define virt_to_pfn(_virt) (PFN_DOWN(to_phys(_virt)))
-#define virt_to_mfn(_virt) (PFN_DOWN(to_phys(_virt)))
-#define mfn_to_virt(_mfn) (to_virt(PFN_PHYS(_mfn)))
-#define pfn_to_virt(_pfn) (to_virt(PFN_PHYS(_pfn)))
-
-#define mfn_to_pfn(x) (x)
-#define pfn_to_mfn(x) (x)
-
-#define virtual_to_mfn(_virt) virt_to_mfn(_virt)
-
-// FIXME
-#define map_frames(f, n) (NULL)
-
-#endif
+++ /dev/null
-#ifndef __ARCH_SCHED_H__
-#define __ARCH_SCHED_H__
-
-#include "arch_limits.h"
-
-static inline struct thread* get_current(void)
-{
- struct thread **current;
- unsigned long sp;
- __asm__ __volatile__ ("mov %0, sp":"=r"(sp));
- current = (void *)(unsigned long)(sp & ~(__STACK_SIZE-1));
- return *current;
-}
-
-void __arch_switch_threads(unsigned long *prevctx, unsigned long *nextctx);
-
-#define arch_switch_threads(prev,next) __arch_switch_threads(&(prev)->sp, &(next)->sp)
-
-#endif /* __ARCH_SCHED_H__ */
+++ /dev/null
-#ifndef __ARCH_ASM_SPINLOCK_H
-#define __ARCH_ASM_SPINLOCK_H
-
-#include "os.h"
-
-#define ARCH_SPIN_LOCK_UNLOCKED { 1 }
-
-/*
- * Simple spin lock operations. There are two variants, one clears IRQ's
- * on the local processor, one does not.
- *
- * We make no fairness assumptions. They have a cost.
- */
-
-#define arch_spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) <= 0)
-#define arch_spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
-
-static inline void _raw_spin_unlock(spinlock_t *lock)
-{
- xchg(&lock->slock, 1);
-}
-
-static inline int _raw_spin_trylock(spinlock_t *lock)
-{
- return xchg(&lock->slock, 0) != 0 ? 1 : 0;
-}
-
-static inline void _raw_spin_lock(spinlock_t *lock)
-{
- volatile int was_locked;
- do {
- was_locked = xchg(&lock->slock, 0) == 0 ? 1 : 0;
- } while(was_locked);
-}
-
-#endif
+++ /dev/null
-#define __WORDSIZE 32
+++ /dev/null
-void gic_init(void);
+++ /dev/null
-/******************************************************************************
- * hypercall-arm.h
- *
- * Copied from XenLinux.
- *
- * Copyright (c) 2002-2004, K A Fraser
- *
- * 64-bit updates:
- * Benjamin Liu <benjamin.liu@intel.com>
- * Jun Nakajima <jun.nakajima@intel.com>
- *
- * This file may be distributed separately from the Linux kernel, or
- * incorporated into other software packages, subject to the following license:
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this source file (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef __HYPERCALL_ARM_H__
-#define __HYPERCALL_ARM_H__
-
-#include <xen/xen.h>
-#include <xen/sched.h>
-#include <xen/xsm/flask_op.h>
-#include <mini-os/mm.h>
-
-int
-HYPERVISOR_sched_op(
- int cmd, void *arg);
-
-static inline int
-HYPERVISOR_shutdown(
- unsigned int reason)
-{
- struct sched_shutdown shutdown = { .reason = reason };
- HYPERVISOR_sched_op(SCHEDOP_shutdown, &shutdown);
-}
-
-int
-HYPERVISOR_memory_op(
- unsigned int cmd, void *arg);
-
-int
-HYPERVISOR_event_channel_op(
- int cmd, void *op);
-
-int
-HYPERVISOR_xen_version(
- int cmd, void *arg);
-
-int
-HYPERVISOR_console_io(
- int cmd, int count, char *str);
-
-int
-HYPERVISOR_physdev_op(
- void *physdev_op);
-
-int
-HYPERVISOR_grant_table_op(
- unsigned int cmd, void *uop, unsigned int count);
-
-int
-HYPERVISOR_vcpu_op(
- int cmd, int vcpuid, void *extra_args);
-
-int
-HYPERVISOR_sysctl(
- unsigned long op);
-
-int
-HYPERVISOR_domctl(
- unsigned long op);
-
-int
-HYPERVISOR_hvm_op(
- unsigned long op, void *arg);
-
-int
-HYPERVISOR_xsm_op(
- struct xen_flask_op *);
-
-#endif /* __HYPERCALL_ARM_H__ */
+++ /dev/null
-#ifndef _OS_H_
-#define _OS_H_
-
-#ifndef __ASSEMBLY__
-
-#include <mini-os/hypervisor.h>
-#include <mini-os/types.h>
-#include <mini-os/compiler.h>
-#include <mini-os/kernel.h>
-#include <xen/xen.h>
-
-void arch_fini(void);
-void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign);
-
-extern void *device_tree;
-
-#define BUG() while(1){asm volatile (".word 0xe7f000f0\n");} /* Undefined instruction; will call our fault handler. */
-
-#define smp_processor_id() 0
-
-#define barrier() __asm__ __volatile__("": : :"memory")
-
-extern shared_info_t *HYPERVISOR_shared_info;
-
-// disable interrupts
-static inline void local_irq_disable(void) {
- __asm__ __volatile__("cpsid i":::"memory");
-}
-
-// enable interrupts
-static inline void local_irq_enable(void) {
- __asm__ __volatile__("cpsie i":::"memory");
-}
-
-#define local_irq_save(x) { \
- __asm__ __volatile__("mrs %0, cpsr;cpsid i":"=r"(x)::"memory"); \
-}
-
-#define local_irq_restore(x) { \
- __asm__ __volatile__("msr cpsr_c, %0"::"r"(x):"memory"); \
-}
-
-#define local_save_flags(x) { \
- __asm__ __volatile__("mrs %0, cpsr":"=r"(x)::"memory"); \
-}
-
-static inline int irqs_disabled(void) {
- int x;
- local_save_flags(x);
- return x & 0x80;
-}
-
-/* We probably only need "dmb" here, but we'll start by being paranoid. */
-#define mb() __asm__("dsb":::"memory");
-#define rmb() __asm__("dsb":::"memory");
-#define wmb() __asm__("dsb":::"memory");
-
-/************************** arm *******************************/
-#ifdef __INSIDE_MINIOS__
-#if defined (__arm__)
-#define xchg(ptr,v) __atomic_exchange_n(ptr, v, __ATOMIC_SEQ_CST)
-
-/**
- * test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to clear
- * @addr: Address to count from
- *
- * Note that @nr may be almost arbitrarily large; this function is not
- * restricted to acting on a single-word quantity.
- *
- * This operation is atomic.
- * If you need a memory barrier, use synch_test_and_clear_bit instead.
- */
-static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
-{
- uint8_t *byte = ((uint8_t *)addr) + (nr >> 3);
- uint8_t bit = 1 << (nr & 7);
- uint8_t orig;
-
- orig = __atomic_fetch_and(byte, ~bit, __ATOMIC_RELAXED);
-
- return (orig & bit) != 0;
-}
-
-/**
- * Atomically set a bit and return the old value.
- * Similar to test_and_clear_bit.
- */
-static __inline__ int test_and_set_bit(int nr, volatile void *base)
-{
- uint8_t *byte = ((uint8_t *)base) + (nr >> 3);
- uint8_t bit = 1 << (nr & 7);
- uint8_t orig;
-
- orig = __atomic_fetch_or(byte, bit, __ATOMIC_RELAXED);
-
- return (orig & bit) != 0;
-}
-
-/**
- * Test whether a bit is set. */
-static __inline__ int test_bit(int nr, const volatile unsigned long *addr)
-{
- const uint8_t *ptr = (const uint8_t *) addr;
- return ((1 << (nr & 7)) & (ptr[nr >> 3])) != 0;
-}
-
-/**
- * Atomically set a bit in memory (like test_and_set_bit but discards result).
- */
-static __inline__ void set_bit(int nr, volatile unsigned long *addr)
-{
- test_and_set_bit(nr, addr);
-}
-
-/**
- * Atomically clear a bit in memory (like test_and_clear_bit but discards result).
- */
-static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
-{
- test_and_clear_bit(nr, addr);
-}
-
-/**
- * __ffs - find first (lowest) set bit in word.
- * @word: The word to search
- *
- * Undefined if no bit exists, so code should check against 0 first.
- */
-static __inline__ unsigned long __ffs(unsigned long word)
-{
- int clz;
-
- /* xxxxx10000 = word
- * xxxxx01111 = word - 1
- * 0000011111 = word ^ (word - 1)
- * 4 = 31 - clz(word ^ (word - 1))
- */
-
- __asm__ (
- "sub r0, %[word], #1\n"
- "eor r0, r0, %[word]\n"
- "clz %[clz], r0\n":
- /* Outputs: */
- [clz] "=r"(clz):
- /* Inputs: */
- [word] "r"(word):
- /* Clobbers: */
- "r0");
-
- return 31 - clz;
-}
-
-#else /* ifdef __arm__ */
-#error "Unsupported architecture"
-#endif
-#endif /* ifdef __INSIDE_MINIOS */
-
-/********************* common arm32 and arm64 ****************************/
-
-/* If *ptr == old, then store new there (and return new).
- * Otherwise, return the old value.
- * Atomic. */
-#define synch_cmpxchg(ptr, old, new) \
-({ __typeof__(*ptr) stored = old; \
- __atomic_compare_exchange_n(ptr, &stored, new, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? new : old; \
-})
-
-/* As test_and_clear_bit, but using __ATOMIC_SEQ_CST */
-static __inline__ int synch_test_and_clear_bit(int nr, volatile void *addr)
-{
- uint8_t *byte = ((uint8_t *)addr) + (nr >> 3);
- uint8_t bit = 1 << (nr & 7);
- uint8_t orig;
-
- orig = __atomic_fetch_and(byte, ~bit, __ATOMIC_SEQ_CST);
-
- return (orig & bit) != 0;
-}
-
-/* As test_and_set_bit, but using __ATOMIC_SEQ_CST */
-static __inline__ int synch_test_and_set_bit(int nr, volatile void *base)
-{
- uint8_t *byte = ((uint8_t *)base) + (nr >> 3);
- uint8_t bit = 1 << (nr & 7);
- uint8_t orig;
-
- orig = __atomic_fetch_or(byte, bit, __ATOMIC_SEQ_CST);
-
- return (orig & bit) != 0;
-}
-
-/* As set_bit, but using __ATOMIC_SEQ_CST */
-static __inline__ void synch_set_bit(int nr, volatile void *addr)
-{
- synch_test_and_set_bit(nr, addr);
-}
-
-/* As clear_bit, but using __ATOMIC_SEQ_CST */
-static __inline__ void synch_clear_bit(int nr, volatile void *addr)
-{
- synch_test_and_clear_bit(nr, addr);
-}
-
-/* As test_bit, but with a following memory barrier. */
-static __inline__ int synch_test_bit(int nr, volatile void *addr)
-{
- int result;
- result = test_bit(nr, addr);
- barrier();
- return result;
-}
-
-#endif /* not assembly */
-
-#endif
+++ /dev/null
-#ifndef _TRAPS_H_
-#define _TRAPS_H_
-
-struct pt_regs {
- unsigned long r0;
- unsigned long r1;
- unsigned long r2;
- unsigned long r3;
- unsigned long r4;
- unsigned long r5;
- unsigned long r6;
- unsigned long r7;
- unsigned long r8;
- unsigned long r9;
- unsigned long r10;
- unsigned long r11;
- unsigned long r12;
-};
-
-#endif
+++ /dev/null
-#include <mini-os/wait.h>
-#include <xen/io/blkif.h>
-#include <mini-os/types.h>
-struct blkfront_dev;
-struct blkfront_aiocb
-{
- struct blkfront_dev *aio_dev;
- uint8_t *aio_buf;
- size_t aio_nbytes;
- off_t aio_offset;
- size_t total_bytes;
- uint8_t is_write;
- void *data;
-
- grant_ref_t gref[BLKIF_MAX_SEGMENTS_PER_REQUEST];
- int n;
-
- void (*aio_cb)(struct blkfront_aiocb *aiocb, int ret);
-};
-struct blkfront_info
-{
- uint64_t sectors;
- unsigned sector_size;
- int mode;
- int info;
- int barrier;
- int flush;
-};
-struct blkfront_dev *init_blkfront(char *nodename, struct blkfront_info *info);
-#ifdef HAVE_LIBC
-#include <sys/stat.h>
-/* POSIX IO functions:
- * use blkfront_open() to get a file descriptor to the block device
- * Don't use the other blkfront posix functions here directly, instead use
- * read(), write(), lseek() and fstat() on the file descriptor
- */
-int blkfront_open(struct blkfront_dev *dev);
-int blkfront_posix_rwop(int fd, uint8_t* buf, size_t count, int write);
-#define blkfront_posix_write(fd, buf, count) blkfront_posix_rwop(fd, (uint8_t*)buf, count, 1)
-#define blkfront_posix_read(fd, buf, count) blkfront_posix_rwop(fd, (uint8_t*)buf, count, 0)
-int blkfront_posix_fstat(int fd, struct stat* buf);
-#endif
-void blkfront_aio(struct blkfront_aiocb *aiocbp, int write);
-#define blkfront_aio_read(aiocbp) blkfront_aio(aiocbp, 0)
-#define blkfront_aio_write(aiocbp) blkfront_aio(aiocbp, 1)
-void blkfront_io(struct blkfront_aiocb *aiocbp, int write);
-#define blkfront_read(aiocbp) blkfront_io(aiocbp, 0)
-#define blkfront_write(aiocbp) blkfront_io(aiocbp, 1)
-void blkfront_aio_push_operation(struct blkfront_aiocb *aiocbp, uint8_t op);
-int blkfront_aio_poll(struct blkfront_dev *dev);
-void blkfront_sync(struct blkfront_dev *dev);
-void shutdown_blkfront(struct blkfront_dev *dev);
-
-extern struct wait_queue_head blkfront_queue;
+++ /dev/null
-#ifndef MINIOS_BYTEORDER_H
-#define MINIOS_BYTEORDER_H
-
-#include <mini-os/byteswap.h>
-#include <mini-os/endian.h>
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define be16_to_cpu(v) bswap_16(v)
-#define be32_to_cpu(v) bswap_32(v)
-#define be64_to_cpu(v) bswap_64(v)
-
-#define le16_to_cpu(v) (v)
-#define le32_to_cpu(v) (v)
-#define le64_to_cpu(v) (v)
-
-#else /*__BIG_ENDIAN*/
-#define be16_to_cpu(v) (v)
-#define be32_to_cpu(v) (v)
-#define be64_to_cpu(v) (v)
-
-#define le16_to_cpu(v) bswap_16(v)
-#define le32_to_cpu(v) bswap_32(v)
-#define le64_to_cpu(v) bswap_64(v)
-
-#endif
-
-#define cpu_to_be16(v) be16_to_cpu(v)
-#define cpu_to_be32(v) be32_to_cpu(v)
-#define cpu_to_be64(v) be64_to_cpu(v)
-
-#define cpu_to_le16(v) le16_to_cpu(v)
-#define cpu_to_le32(v) le32_to_cpu(v)
-#define cpu_to_le64(v) le64_to_cpu(v)
-
-
-#endif
+++ /dev/null
-#ifndef _BYTESWAP_H_
-#define _BYTESWAP_H_
-
-/* Unfortunately not provided by newlib. */
-
-#include <mini-os/types.h>
-
-#define bswap_16(x) ((uint16_t)( \
- (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
- (((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
-
-/* Use gcc optimized versions if they exist */
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
-#define bswap_32(v) __builtin_bswap32(v)
-#define bswap_64(v) __builtin_bswap64(v)
-#else
-
-#define bswap_32(x) ((uint32_t)( \
- (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
- (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
- (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
- (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
-
-#define bswap_64(x) ((uint64_t)( \
- (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
- (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
- (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
- (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
- (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
- (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
- (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
- (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
-
-#endif
-
-
-
-
-#endif /* _BYTESWAP_H */
+++ /dev/null
-#ifndef __MINIOS_COMPILER_H_
-#define __MINIOS_COMPILER_H_
-
-#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
-#define __builtin_expect(x, expected_value) (x)
-#endif
-#define unlikely(x) __builtin_expect(!!(x),0)
-#define likely(x) __builtin_expect(!!(x),1)
-
-#endif /* __MINIOS_COMPILER_H_ */
+++ /dev/null
-/*
- ****************************************************************************
- * (C) 2006 - Grzegorz Milos - Cambridge University
- ****************************************************************************
- *
- * File: console.h
- * Author: Grzegorz Milos
- * Changes:
- *
- * Date: Mar 2006
- *
- * Environment: Xen Minimal OS
- * Description: Console interface.
- *
- * Handles console I/O. Defines printk.
- *
- ****************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#ifndef _LIB_CONSOLE_H_
-#define _LIB_CONSOLE_H_
-
-#include <mini-os/os.h>
-#include <mini-os/traps.h>
-#include <mini-os/types.h>
-#include <xen/grant_table.h>
-#include <xenbus.h>
-#include <xen/io/console.h>
-#include <stdarg.h>
-
-struct consfront_dev {
- domid_t dom;
-
- struct xencons_interface *ring;
- grant_ref_t ring_ref;
- evtchn_port_t evtchn;
-
- char *nodename;
- char *backend;
-
- xenbus_event_queue events;
-
-#ifdef HAVE_LIBC
- int fd;
-#endif
-};
-
-
-
-void print(int direct, const char *fmt, va_list args);
-void printk(const char *fmt, ...);
-void xprintk(const char *fmt, ...);
-
-#define tprintk(_fmt, _args...) printk("[%s] " _fmt, current->name, ##_args)
-
-void xencons_rx(char *buf, unsigned len, struct pt_regs *regs);
-void xencons_tx(void);
-
-void init_console(void);
-void console_print(struct consfront_dev *dev, char *data, int length);
-void fini_console(struct consfront_dev *dev);
-
-/* Low level functions defined in xencons_ring.c */
-extern struct wait_queue_head console_queue;
-struct consfront_dev *xencons_ring_init(void);
-struct consfront_dev *init_consfront(char *_nodename);
-int xencons_ring_send(struct consfront_dev *dev, const char *data, unsigned len);
-int xencons_ring_send_no_notify(struct consfront_dev *dev, const char *data, unsigned len);
-int xencons_ring_avail(struct consfront_dev *dev);
-int xencons_ring_recv(struct consfront_dev *dev, char *data, unsigned len);
-void free_consfront(struct consfront_dev *dev);
-
-#endif /* _LIB_CONSOLE_H_ */
+++ /dev/null
-#ifndef _CTYPE_H
-#define _CTYPE_H
-
-#ifdef HAVE_LIBC
-#include_next <ctype.h>
-#else
-/*
- * NOTE! This ctype does not handle EOF like the standard C
- * library is required to.
- */
-
-#define _U 0x01 /* upper */
-#define _L 0x02 /* lower */
-#define _D 0x04 /* digit */
-#define _C 0x08 /* cntrl */
-#define _P 0x10 /* punct */
-#define _S 0x20 /* white space (space/lf/tab) */
-#define _X 0x40 /* hex digit */
-#define _SP 0x80 /* hard space (0x20) */
-
-
-extern unsigned char _ctype[];
-
-#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
-
-#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
-#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
-#define iscntrl(c) ((__ismask(c)&(_C)) != 0)
-#define isdigit(c) ((__ismask(c)&(_D)) != 0)
-#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
-#define islower(c) ((__ismask(c)&(_L)) != 0)
-#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
-#define ispunct(c) ((__ismask(c)&(_P)) != 0)
-#define isspace(c) ((__ismask(c)&(_S)) != 0)
-#define isupper(c) ((__ismask(c)&(_U)) != 0)
-#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
-
-#define isascii(c) (((unsigned char)(c))<=0x7f)
-#define toascii(c) (((unsigned char)(c))&0x7f)
-
-static inline unsigned char __tolower(unsigned char c)
-{
- if (isupper(c))
- c -= 'A'-'a';
- return c;
-}
-
-static inline unsigned char __toupper(unsigned char c)
-{
- if (islower(c))
- c -= 'a'-'A';
- return c;
-}
-
-#define tolower(c) __tolower(c)
-#define toupper(c) __toupper(c)
-
-#endif
-
-#endif
+++ /dev/null
-#ifndef _ENDIAN_H_
-#define _ENDIAN_H_
-
-#define __LITTLE_ENDIAN 1234
-#define __BIG_ENDIAN 4321
-#define __PDP_ENDIAN 3412
-
-#define ARCH_ENDIAN_H
-/* This will define __BYTE_ORDER for the current arch */
-#include <arch_endian.h>
-#undef ARCH_ENDIAN_H
-
-#include <arch_wordsize.h>
-
-#define BYTE_ORDER __BYTE_ORDER
-#define BIG_ENDIAN __BIG_ENDIAN
-#define LITTLE_ENDIAN __LITTLE_ENDIAN
-
-#endif /* endian.h */
+++ /dev/null
-#ifndef _ERR_H
-#define _ERR_H
-
-#include <mini-os/errno.h>
-
-/*
- * Kernel pointers have redundant information, so we can use a
- * scheme where we can return either an error code or a dentry
- * pointer with the same return value.
- *
- * This should be a per-architecture thing, to allow different
- * error and pointer decisions.
- */
-#define IS_ERR_VALUE(x) ((x) > (unsigned long)-1000L)
-
-static inline void *ERR_PTR(long error)
-{
- return (void *) error;
-}
-
-static inline long PTR_ERR(const void *ptr)
-{
- return (long) ptr;
-}
-
-static inline long IS_ERR(const void *ptr)
-{
- return IS_ERR_VALUE((unsigned long)ptr);
-}
-
-#endif /* _LINUX_ERR_H */
+++ /dev/null
-#ifndef _ERRNO_BASE_H
-#define _ERRNO_BASE_H
-
-#define EPERM 1 /* Operation not permitted */
-#define ENOENT 2 /* No such file or directory */
-#define ESRCH 3 /* No such process */
-#define EINTR 4 /* Interrupted system call */
-#define EIO 5 /* I/O error */
-#define ENXIO 6 /* No such device or address */
-#define E2BIG 7 /* Argument list too long */
-#define ENOEXEC 8 /* Exec format error */
-#define EBADF 9 /* Bad file number */
-#define ECHILD 10 /* No child processes */
-#define EAGAIN 11 /* Try again */
-#define ENOMEM 12 /* Out of memory */
-#define EACCES 13 /* Permission denied */
-#define EFAULT 14 /* Bad address */
-#define ENOTBLK 15 /* Block device required */
-#define EBUSY 16 /* Device or resource busy */
-#define EEXIST 17 /* File exists */
-#define EXDEV 18 /* Cross-device link */
-#define ENODEV 19 /* No such device */
-#define ENOTDIR 20 /* Not a directory */
-#define EISDIR 21 /* Is a directory */
-#define EINVAL 22 /* Invalid argument */
-#define ENFILE 23 /* File table overflow */
-#define EMFILE 24 /* Too many open files */
-#define ENOTTY 25 /* Not a typewriter */
-#define ETXTBSY 26 /* Text file busy */
-#define EFBIG 27 /* File too large */
-#define ENOSPC 28 /* No space left on device */
-#define ESPIPE 29 /* Illegal seek */
-#define EROFS 30 /* Read-only file system */
-#define EMLINK 31 /* Too many links */
-#define EPIPE 32 /* Broken pipe */
-#define EDOM 33 /* Math argument out of domain of func */
-#define ERANGE 34 /* Math result not representable */
-
-#endif
+++ /dev/null
-#ifndef _ERRNO_H
-#define _ERRNO_H
-
-#include <mini-os/errno-base.h>
-
-typedef int error_t;
-
-#define EDEADLK 35 /* Resource deadlock would occur */
-#define ENAMETOOLONG 36 /* File name too long */
-#define ENOLCK 37 /* No record locks available */
-#define ENOSYS 38 /* Function not implemented */
-#define ENOTEMPTY 39 /* Directory not empty */
-#define ELOOP 40 /* Too many symbolic links encountered */
-#define EWOULDBLOCK EAGAIN /* Operation would block */
-#define ENOMSG 42 /* No message of desired type */
-#define EIDRM 43 /* Identifier removed */
-#define ECHRNG 44 /* Channel number out of range */
-#define EL2NSYNC 45 /* Level 2 not synchronized */
-#define EL3HLT 46 /* Level 3 halted */
-#define EL3RST 47 /* Level 3 reset */
-#define ELNRNG 48 /* Link number out of range */
-#define EUNATCH 49 /* Protocol driver not attached */
-#define ENOCSI 50 /* No CSI structure available */
-#define EL2HLT 51 /* Level 2 halted */
-#define EBADE 52 /* Invalid exchange */
-#define EBADR 53 /* Invalid request descriptor */
-#define EXFULL 54 /* Exchange full */
-#define ENOANO 55 /* No anode */
-#define EBADRQC 56 /* Invalid request code */
-#define EBADSLT 57 /* Invalid slot */
-
-#define EDEADLOCK EDEADLK
-
-#define EBFONT 59 /* Bad font file format */
-#define ENOSTR 60 /* Device not a stream */
-#define ENODATA 61 /* No data available */
-#define ETIME 62 /* Timer expired */
-#define ENOSR 63 /* Out of streams resources */
-#define ENONET 64 /* Machine is not on the network */
-#define ENOPKG 65 /* Package not installed */
-#define EREMOTE 66 /* Object is remote */
-#define ENOLINK 67 /* Link has been severed */
-#define EADV 68 /* Advertise error */
-#define ESRMNT 69 /* Srmount error */
-#define ECOMM 70 /* Communication error on send */
-#define EPROTO 71 /* Protocol error */
-#define EMULTIHOP 72 /* Multihop attempted */
-#define EDOTDOT 73 /* RFS specific error */
-#define EBADMSG 74 /* Not a data message */
-#define EOVERFLOW 75 /* Value too large for defined data type */
-#define ENOTUNIQ 76 /* Name not unique on network */
-#define EBADFD 77 /* File descriptor in bad state */
-#define EREMCHG 78 /* Remote address changed */
-#define ELIBACC 79 /* Can not access a needed shared library */
-#define ELIBBAD 80 /* Accessing a corrupted shared library */
-#define ELIBSCN 81 /* .lib section in a.out corrupted */
-#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
-#define ELIBEXEC 83 /* Cannot exec a shared library directly */
-#define EILSEQ 84 /* Illegal byte sequence */
-#define ERESTART 85 /* Interrupted system call should be restarted */
-#define ESTRPIPE 86 /* Streams pipe error */
-#define EUSERS 87 /* Too many users */
-#define ENOTSOCK 88 /* Socket operation on non-socket */
-#define EDESTADDRREQ 89 /* Destination address required */
-#define EMSGSIZE 90 /* Message too long */
-#define EPROTOTYPE 91 /* Protocol wrong type for socket */
-#define ENOPROTOOPT 92 /* Protocol not available */
-#define EPROTONOSUPPORT 93 /* Protocol not supported */
-#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
-#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
-#define ENOTSUP EOPNOTSUPP
-#define EPFNOSUPPORT 96 /* Protocol family not supported */
-#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
-#define EADDRINUSE 98 /* Address already in use */
-#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
-#define ENETDOWN 100 /* Network is down */
-#define ENETUNREACH 101 /* Network is unreachable */
-#define ENETRESET 102 /* Network dropped connection because of reset */
-#define ECONNABORTED 103 /* Software caused connection abort */
-#define ECONNRESET 104 /* Connection reset by peer */
-#define ENOBUFS 105 /* No buffer space available */
-#define EISCONN 106 /* Transport endpoint is already connected */
-#define ENOTCONN 107 /* Transport endpoint is not connected */
-#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
-#define ETOOMANYREFS 109 /* Too many references: cannot splice */
-#define ETIMEDOUT 110 /* Connection timed out */
-#define ECONNREFUSED 111 /* Connection refused */
-#define EHOSTDOWN 112 /* Host is down */
-#define EHOSTUNREACH 113 /* No route to host */
-#define EALREADY 114 /* Operation already in progress */
-#define EINPROGRESS 115 /* Operation now in progress */
-#define ESTALE 116 /* Stale NFS file handle */
-#define EUCLEAN 117 /* Structure needs cleaning */
-#define ENOTNAM 118 /* Not a XENIX named type file */
-#define ENAVAIL 119 /* No XENIX semaphores available */
-#define EISNAM 120 /* Is a named type file */
-#define EREMOTEIO 121 /* Remote I/O error */
-#define EDQUOT 122 /* Quota exceeded */
-
-#define ENOMEDIUM 123 /* No medium found */
-#define EMEDIUMTYPE 124 /* Wrong medium type */
-#define ECANCELED 125 /* Operation Canceled */
-#define ENOKEY 126 /* Required key not available */
-#define EKEYEXPIRED 127 /* Key has expired */
-#define EKEYREVOKED 128 /* Key has been revoked */
-#define EKEYREJECTED 129 /* Key was rejected by service */
-
-/* for robust mutexes */
-#define EOWNERDEAD 130 /* Owner died */
-#define ENOTRECOVERABLE 131 /* State not recoverable */
-
-
-#define EFTYPE 132 /* Inappropriate file type or format */
-
-#ifdef HAVE_LIBC
-#include <mini-os/sched.h>
-extern int errno;
-#define ERRNO
-#define errno (get_current()->reent._errno)
-#endif
-
-#endif
+++ /dev/null
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- * (C) 2005 - Grzegorz Milos - Intel Reseach Cambridge
- ****************************************************************************
- *
- * File: events.h
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes: Grzegorz Milos (gm281@cam.ac.uk)
- *
- * Date: Jul 2003, changes Jun 2005
- *
- * Environment: Xen Minimal OS
- * Description: Deals with events on the event channels
- *
- ****************************************************************************
- */
-
-#ifndef _EVENTS_H_
-#define _EVENTS_H_
-
-#include<mini-os/traps.h>
-#include<xen/event_channel.h>
-
-typedef void (*evtchn_handler_t)(evtchn_port_t, struct pt_regs *, void *);
-
-/* prototypes */
-void arch_init_events(void);
-
-/* Called by fini_events to close any ports opened by arch-specific code. */
-void arch_unbind_ports(void);
-
-void arch_fini_events(void);
-
-int do_event(evtchn_port_t port, struct pt_regs *regs);
-evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data);
-evtchn_port_t bind_pirq(uint32_t pirq, int will_share, evtchn_handler_t handler, void *data);
-evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler,
- void *data);
-void unbind_evtchn(evtchn_port_t port);
-void init_events(void);
-int evtchn_alloc_unbound(domid_t pal, evtchn_handler_t handler,
- void *data, evtchn_port_t *port);
-int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port,
- evtchn_handler_t handler, void *data,
- evtchn_port_t *local_port);
-int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size);
-void unbind_all_ports(void);
-
-static inline int notify_remote_via_evtchn(evtchn_port_t port)
-{
- evtchn_send_t op;
- op.port = port;
- return HYPERVISOR_event_channel_op(EVTCHNOP_send, &op);
-}
-
-void fini_events(void);
-
-#endif /* _EVENTS_H_ */
+++ /dev/null
-#include <xen/io/kbdif.h>
-#include <xen/io/fbif.h>
-#include <mini-os/semaphore.h>
-#include <mini-os/wait.h>
-
-/* from <linux/input.h> */
-#ifndef BTN_LEFT
-#define BTN_LEFT 0x110
-#endif
-#ifndef BTN_RIGHT
-#define BTN_RIGHT 0x111
-#endif
-#ifndef BTN_MIDDLE
-#define BTN_MIDDLE 0x112
-#endif
-#ifndef KEY_Q
-#define KEY_Q 16
-#endif
-#ifndef KEY_MAX
-#define KEY_MAX 0x1ff
-#endif
-
-
-struct kbdfront_dev;
-struct kbdfront_dev *init_kbdfront(char *nodename, int abs_pointer);
-#ifdef HAVE_LIBC
-int kbdfront_open(struct kbdfront_dev *dev);
-#endif
-
-int kbdfront_receive(struct kbdfront_dev *dev, union xenkbd_in_event *buf, int n);
-extern struct wait_queue_head kbdfront_queue;
-
-void shutdown_kbdfront(struct kbdfront_dev *dev);
-
-
-struct fbfront_dev *init_fbfront(char *nodename, unsigned long *mfns, int width, int height, int depth, int stride, int n);
-#ifdef HAVE_LIBC
-int fbfront_open(struct fbfront_dev *dev);
-#endif
-
-int fbfront_receive(struct fbfront_dev *dev, union xenfb_in_event *buf, int n);
-extern struct wait_queue_head fbfront_queue;
-void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int height);
-void fbfront_resize(struct fbfront_dev *dev, int width, int height, int stride, int depth, int offset);
-
-void shutdown_fbfront(struct fbfront_dev *dev);
+++ /dev/null
-#ifndef _I386_FCNTL_H
-#define _I386_FCNTL_H
-
-#ifdef HAVE_LIBC
-#include_next <fcntl.h>
-#else
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT 040000 /* direct disk access hint */
-#define O_LARGEFILE 0100000
-#define O_DIRECTORY 0200000 /* must be a directory */
-#define O_NOFOLLOW 0400000 /* don't follow links */
-#define O_NOATIME 01000000
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
-
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-/*
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
-*/
-
-#endif
-
-int open(const char *path, int flags, ...) asm("open64");
-int fcntl(int fd, int cmd, ...);
-
-#endif
+++ /dev/null
-#ifndef __GNTMAP_H__
-#define __GNTMAP_H__
-
-#include <os.h>
-
-/*
- * Please consider struct gntmap opaque. If instead you choose to disregard
- * this message, I insist that you keep an eye out for raptors.
- */
-struct gntmap {
- int nentries;
- struct gntmap_entry *entries;
-};
-
-int
-gntmap_set_max_grants(struct gntmap *map, int count);
-
-int
-gntmap_munmap(struct gntmap *map, unsigned long start_address, int count);
-
-void*
-gntmap_map_grant_refs(struct gntmap *map,
- uint32_t count,
- uint32_t *domids,
- int domids_stride,
- uint32_t *refs,
- int writable);
-
-void
-gntmap_init(struct gntmap *map);
-
-void
-gntmap_fini(struct gntmap *map);
-
-#endif /* !__GNTMAP_H__ */
+++ /dev/null
-#ifndef __GNTTAB_H__
-#define __GNTTAB_H__
-
-#include <xen/grant_table.h>
-
-void init_gnttab(void);
-grant_ref_t gnttab_alloc_and_grant(void **map);
-grant_ref_t gnttab_grant_access(domid_t domid, unsigned long frame,
- int readonly);
-grant_ref_t gnttab_grant_transfer(domid_t domid, unsigned long pfn);
-unsigned long gnttab_end_transfer(grant_ref_t gref);
-int gnttab_end_access(grant_ref_t ref);
-const char *gnttabop_error(int16_t status);
-void fini_gnttab(void);
-grant_entry_t *arch_init_gnttab(int nr_grant_frames);
-
-#endif /* !__GNTTAB_H__ */
+++ /dev/null
-/******************************************************************************
- * hypervisor.h
- *
- * Hypervisor handling.
- *
- *
- * Copyright (c) 2002, K A Fraser
- * Copyright (c) 2005, Grzegorz Milos
- * Updates: Aravindh Puthiyaparambil <aravindh.puthiyaparambil@unisys.com>
- */
-
-#ifndef _HYPERVISOR_H_
-#define _HYPERVISOR_H_
-
-#include <mini-os/types.h>
-#include <xen/xen.h>
-#if defined(__i386__)
-#include <hypercall-x86_32.h>
-#elif defined(__x86_64__)
-#include <hypercall-x86_64.h>
-#elif defined(__arm__) || defined(__aarch64__)
-#include <hypercall-arm.h>
-#else
-#error "Unsupported architecture"
-#endif
-#include <mini-os/traps.h>
-
-/*
- * a placeholder for the start of day information passed up from the hypervisor
- */
-union start_info_union
-{
- start_info_t start_info;
- char padding[512];
-};
-extern union start_info_union start_info_union;
-#define start_info (start_info_union.start_info)
-
-/* hypervisor.c */
-void force_evtchn_callback(void);
-void do_hypervisor_callback(struct pt_regs *regs);
-void mask_evtchn(uint32_t port);
-void unmask_evtchn(uint32_t port);
-void clear_evtchn(uint32_t port);
-
-extern int in_callback;
-
-#endif /* __HYPERVISOR_H__ */
+++ /dev/null
-/**
- * Copyright (C) 2009 Netronome Systems, Inc. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef _IOREMAP_H_
-#define _IOREMAP_H_
-
-void *ioremap(unsigned long phys_addr, unsigned long size);
-void *ioremap_nocache(unsigned long phys_addr, unsigned long size);
-void iounmap(void *virt_addr, unsigned long size);
-
-#endif /* _IOREMAP_H_ */
-
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 indent-tabs-mode:nil -*- */
+++ /dev/null
-#ifndef MINIOS_IORW_H
-#define MINIOS_IORW_H
-
-#include <mini-os/types.h>
-
-void iowrite8(volatile void* addr, uint8_t val);
-void iowrite16(volatile void* addr, uint16_t val);
-void iowrite32(volatile void* addr, uint32_t val);
-void iowrite64(volatile void* addr, uint64_t val);
-
-uint8_t ioread8(volatile void* addr);
-uint16_t ioread16(volatile void* addr);
-uint32_t ioread32(volatile void* addr);
-uint64_t ioread64(volatile void* addr);
-
-#endif
+++ /dev/null
-#ifndef _KERNEL_H_
-#define _KERNEL_H_
-
-void start_kernel(void);
-void do_exit(void) __attribute__((noreturn));
-void arch_do_exit(void);
-void stop_kernel(void);
-
-#endif /* _KERNEL_H_ */
+++ /dev/null
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
- *
- * File: lib.h
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes:
- *
- * Date: Aug 2003
- *
- * Environment: Xen Minimal OS
- * Description: Random useful library functions, from Linux'
- * include/linux/kernel.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _LIB_GPL_H_
-#define _LIB_GPL_H_
-
-#ifndef HAVE_LIBC
-/* printing */
-extern unsigned long simple_strtoul(const char *,char **,unsigned int);
-extern long simple_strtol(const char *,char **,unsigned int);
-extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
-extern long long simple_strtoll(const char *,char **,unsigned int);
-
-extern int sprintf(char * buf, const char * fmt, ...)
- __attribute__ ((format (printf, 2, 3)));
-extern int vsprintf(char *buf, const char *, va_list)
- __attribute__ ((format (printf, 2, 0)));
-extern int snprintf(char * buf, size_t size, const char * fmt, ...)
- __attribute__ ((format (printf, 3, 4)));
-extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
- __attribute__ ((format (printf, 3, 0)));
-extern int scnprintf(char * buf, size_t size, const char * fmt, ...)
- __attribute__ ((format (printf, 3, 4)));
-extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
- __attribute__ ((format (printf, 3, 0)));
-extern int sscanf(const char *, const char *, ...)
- __attribute__ ((format (scanf, 2, 3)));
-extern int vsscanf(const char *, const char *, va_list)
- __attribute__ ((format (scanf, 2, 0)));
-#endif
-
-#endif /* _LIB_GPL_H_ */
+++ /dev/null
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
- *
- * File: lib.h
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes:
- *
- * Date: Aug 2003
- *
- * Environment: Xen Minimal OS
- * Description: Random useful library functions, contains some freebsd stuff
- *
- ****************************************************************************
- * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
- ****************************************************************************
- *
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#ifndef _LIB_H_
-#define _LIB_H_
-
-#include <stdarg.h>
-#include <stddef.h>
-#include <xen/xen.h>
-#include <xen/event_channel.h>
-#include "gntmap.h"
-
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
-#define BUILD_BUG_ON(cond) ({ _Static_assert(!(cond), "!(" #cond ")"); })
-#define BUILD_BUG_ON_ZERO(cond) \
- sizeof(struct { _Static_assert(!(cond), "!(" #cond ")"); })
-#else
-#define BUILD_BUG_ON_ZERO(cond) sizeof(struct { int:-!!(cond); })
-#define BUILD_BUG_ON(cond) ((void)BUILD_BUG_ON_ZERO(cond))
-#endif
-
-#ifdef HAVE_LIBC
-#include <sys/queue.h>
-#include <stdio.h>
-#else
-#include <lib-gpl.h>
-#endif
-
-#ifdef HAVE_LIBC
-#include <string.h>
-#else
-/* string and memory manipulation */
-
-/*
- * From:
- * @(#)libkern.h 8.1 (Berkeley) 6/10/93
- * $FreeBSD$
- */
-int memcmp(const void *b1, const void *b2, size_t len);
-
-char *strcat(char * __restrict, const char * __restrict);
-int strcmp(const char *, const char *);
-char *strcpy(char * __restrict, const char * __restrict);
-
-char *strdup(const char *__restrict);
-
-size_t strlen(const char *);
-
-int strncmp(const char *, const char *, size_t);
-char *strncpy(char * __restrict, const char * __restrict, size_t);
-
-char *strstr(const char *, const char *);
-
-void *memset(void *, int, size_t);
-
-char *strchr(const char *p, int ch);
-char *strrchr(const char *p, int ch);
-
-/* From:
- * @(#)systm.h 8.7 (Berkeley) 3/29/95
- * $FreeBSD$
- */
-void *memcpy(void *to, const void *from, size_t len);
-
-size_t strnlen(const char *, size_t);
-#endif
-
-#include <mini-os/console.h>
-
-#define RAND_MIX 2654435769U
-
-int rand(void);
-
-#include <mini-os/xenbus.h>
-
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
-#define ASSERT(x) \
-do { \
- if (!(x)) { \
- printk("ASSERTION FAILED: %s at %s:%d.\n", \
- # x , \
- __FILE__, \
- __LINE__); \
- BUG(); \
- } \
-} while(0)
-
-#define BUG_ON(x) ASSERT(!(x))
-
-/* Consistency check as much as possible. */
-void sanity_check(void);
-
-#ifdef HAVE_LIBC
-enum fd_type {
- FTYPE_NONE = 0,
- FTYPE_CONSOLE,
- FTYPE_FILE,
- FTYPE_XENBUS,
- FTYPE_XC,
- FTYPE_EVTCHN,
- FTYPE_GNTMAP,
- FTYPE_SOCKET,
- FTYPE_TAP,
- FTYPE_BLK,
- FTYPE_KBD,
- FTYPE_FB,
- FTYPE_MEM,
- FTYPE_SAVEFILE,
- FTYPE_TPMFRONT,
- FTYPE_TPM_TIS,
-};
-
-LIST_HEAD(evtchn_port_list, evtchn_port_info);
-
-struct evtchn_port_info {
- LIST_ENTRY(evtchn_port_info) list;
- evtchn_port_t port;
- unsigned long pending;
- int bound;
-};
-
-extern struct file {
- enum fd_type type;
- union {
- struct {
- /* lwIP fd */
- int fd;
- } socket;
- struct {
- /* FS import fd */
- int fd;
- off_t offset;
- } file;
- struct {
- struct evtchn_port_list ports;
- } evtchn;
- struct gntmap gntmap;
- struct {
- struct netfront_dev *dev;
- } tap;
- struct {
- struct blkfront_dev *dev;
- off_t offset;
- } blk;
- struct {
- struct kbdfront_dev *dev;
- } kbd;
- struct {
- struct fbfront_dev *dev;
- } fb;
- struct {
- struct consfront_dev *dev;
- } cons;
-#ifdef CONFIG_TPMFRONT
- struct {
- struct tpmfront_dev *dev;
- int respgot;
- off_t offset;
- } tpmfront;
-#endif
-#ifdef CONFIG_TPM_TIS
- struct {
- struct tpm_chip *dev;
- int respgot;
- off_t offset;
- } tpm_tis;
-#endif
-#ifdef CONFIG_XENBUS
- struct {
- /* To each xenbus FD is associated a queue of watch events for this
- * FD. */
- xenbus_event_queue events;
- } xenbus;
-#endif
- };
- int read; /* maybe available for read */
-} files[];
-
-int alloc_fd(enum fd_type type);
-void close_all_files(void);
-extern struct thread *main_thread;
-void sparse(unsigned long data, size_t size);
-#endif
-
-#endif /* _LIB_H_ */
+++ /dev/null
-#ifndef _LINUX_TYPES_H_
-#define _LINUX_TYPES_H_
-#include <mini-os/types.h>
-typedef uint64_t __u64;
-#endif /* _LINUX_TYPES_H_ */
+++ /dev/null
-/*
- * lwipopts.h
- *
- * Configuration for lwIP running on mini-os
- *
- * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
- */
-
-#ifndef __LWIP_LWIPOPTS_H__
-#define __LWIP_LWIPOPTS_H__
-
-#define SYS_LIGHTWEIGHT_PROT 1
-#define MEM_LIBC_MALLOC 1
-#define LWIP_TIMEVAL_PRIVATE 0
-#define LWIP_DHCP 1
-#define LWIP_COMPAT_SOCKETS 0
-#define LWIP_IGMP 1
-#define LWIP_USE_HEAP_FROM_INTERRUPT 1
-#define MEMP_NUM_SYS_TIMEOUT 10
-#define TCP_SND_BUF 3000
-#define TCP_MSS 1500
-
-#endif /* __LWIP_LWIPOPTS_H__ */
+++ /dev/null
-WARNING - DO NOT EDIT THINGS IN THIS DIRECTORY
-----------------------------------------------
-
-These files were obtained elsewhere and should only be updated by
-copying new versions from the source location, as documented below:
-
-bsd-COPYRIGHT
-bsd-sys-queue.h
-bsd-queue.3
-
- Obtained from the FreeBSD SVN using the following commands:
- svn co -r 221843 svn://svn.freebsd.org/base/head/sys/sys/
- svn co -r 221843 svn://svn.freebsd.org/base/head/share/man/man3
- svn cat -r 221843 http://svn.freebsd.org/base/head/COPYRIGHT >tools/libxl/external/bsd-COPYRIGHT
-
-Exceptions:
-
-README
-
- This file
-
-bsd-sys-queue-h-seddery
-
- Script to transform the above into a new namespace.
+++ /dev/null
-# $FreeBSD$
-# @(#)COPYRIGHT 8.2 (Berkeley) 3/21/94
-
-The compilation of software known as FreeBSD is distributed under the
-following terms:
-
-Copyright (c) 1992-2011 The FreeBSD Project. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
-The 4.4BSD and 4.4BSD-Lite software is distributed under the following
-terms:
-
-All of the documentation and software included in the 4.4BSD and 4.4BSD-Lite
-Releases is copyrighted by The Regents of the University of California.
-
-Copyright 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
- The Regents of the University of California. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-3. All advertising materials mentioning features or use of this software
- must display the following acknowledgement:
-This product includes software developed by the University of
-California, Berkeley and its contributors.
-4. Neither the name of the University nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
-The Institute of Electrical and Electronics Engineers and the American
-National Standards Committee X3, on Information Processing Systems have
-given us permission to reprint portions of their documentation.
-
-In the following statement, the phrase ``this text'' refers to portions
-of the system documentation.
-
-Portions of this text are reprinted and reproduced in electronic form in
-the second BSD Networking Software Release, from IEEE Std 1003.1-1988, IEEE
-Standard Portable Operating System Interface for Computer Environments
-(POSIX), copyright C 1988 by the Institute of Electrical and Electronics
-Engineers, Inc. In the event of any discrepancy between these versions
-and the original IEEE Standard, the original IEEE Standard is the referee
-document.
-
-In the following statement, the phrase ``This material'' refers to portions
-of the system documentation.
-
-This material is reproduced with permission from American National
-Standards Committee X3, on Information Processing Systems. Computer and
-Business Equipment Manufacturers Association (CBEMA), 311 First St., NW,
-Suite 500, Washington, DC 20001-2178. The developmental work of
-Programming Language C was completed by the X3J11 Technical Committee.
-
-The views and conclusions contained in the software and documentation are
-those of the authors and should not be interpreted as representing official
-policies, either expressed or implied, of the Regents of the University
-of California.
-
-
-NOTE: The copyright of UC Berkeley's Berkeley Software Distribution ("BSD")
-source has been updated. The copyright addendum may be found at
-ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change and is
-included below.
-
-July 22, 1999
-
-To All Licensees, Distributors of Any Version of BSD:
-
-As you know, certain of the Berkeley Software Distribution ("BSD") source
-code files require that further distributions of products containing all or
-portions of the software, acknowledge within their advertising materials
-that such products contain software developed by UC Berkeley and its
-contributors.
-
-Specifically, the provision reads:
-
-" * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors."
-
-Effective immediately, licensees and distributors are no longer required to
-include the acknowledgement within advertising materials. Accordingly, the
-foregoing paragraph of those BSD Unix files containing it is hereby deleted
-in its entirety.
-
-William Hoskins
-Director, Office of Technology Licensing
-University of California, Berkeley
+++ /dev/null
-.\" Copyright (c) 1993
-.\" The Regents of the University of California. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" @(#)queue.3 8.2 (Berkeley) 1/24/94
-.\" $FreeBSD$
-.\"
-.Dd May 13, 2011
-.Dt QUEUE 3
-.Os
-.Sh NAME
-.Nm SLIST_EMPTY ,
-.Nm SLIST_ENTRY ,
-.Nm SLIST_FIRST ,
-.Nm SLIST_FOREACH ,
-.Nm SLIST_FOREACH_SAFE ,
-.Nm SLIST_HEAD ,
-.Nm SLIST_HEAD_INITIALIZER ,
-.Nm SLIST_INIT ,
-.Nm SLIST_INSERT_AFTER ,
-.Nm SLIST_INSERT_HEAD ,
-.Nm SLIST_NEXT ,
-.Nm SLIST_REMOVE_AFTER ,
-.Nm SLIST_REMOVE_HEAD ,
-.Nm SLIST_REMOVE ,
-.Nm SLIST_SWAP ,
-.Nm STAILQ_CONCAT ,
-.Nm STAILQ_EMPTY ,
-.Nm STAILQ_ENTRY ,
-.Nm STAILQ_FIRST ,
-.Nm STAILQ_FOREACH ,
-.Nm STAILQ_FOREACH_SAFE ,
-.Nm STAILQ_HEAD ,
-.Nm STAILQ_HEAD_INITIALIZER ,
-.Nm STAILQ_INIT ,
-.Nm STAILQ_INSERT_AFTER ,
-.Nm STAILQ_INSERT_HEAD ,
-.Nm STAILQ_INSERT_TAIL ,
-.Nm STAILQ_LAST ,
-.Nm STAILQ_NEXT ,
-.Nm STAILQ_REMOVE_AFTER ,
-.Nm STAILQ_REMOVE_HEAD ,
-.Nm STAILQ_REMOVE ,
-.Nm STAILQ_SWAP ,
-.Nm LIST_EMPTY ,
-.Nm LIST_ENTRY ,
-.Nm LIST_FIRST ,
-.Nm LIST_FOREACH ,
-.Nm LIST_FOREACH_SAFE ,
-.Nm LIST_HEAD ,
-.Nm LIST_HEAD_INITIALIZER ,
-.Nm LIST_INIT ,
-.Nm LIST_INSERT_AFTER ,
-.Nm LIST_INSERT_BEFORE ,
-.Nm LIST_INSERT_HEAD ,
-.Nm LIST_NEXT ,
-.Nm LIST_REMOVE ,
-.Nm LIST_SWAP ,
-.Nm TAILQ_CONCAT ,
-.Nm TAILQ_EMPTY ,
-.Nm TAILQ_ENTRY ,
-.Nm TAILQ_FIRST ,
-.Nm TAILQ_FOREACH ,
-.Nm TAILQ_FOREACH_SAFE ,
-.Nm TAILQ_FOREACH_REVERSE ,
-.Nm TAILQ_FOREACH_REVERSE_SAFE ,
-.Nm TAILQ_HEAD ,
-.Nm TAILQ_HEAD_INITIALIZER ,
-.Nm TAILQ_INIT ,
-.Nm TAILQ_INSERT_AFTER ,
-.Nm TAILQ_INSERT_BEFORE ,
-.Nm TAILQ_INSERT_HEAD ,
-.Nm TAILQ_INSERT_TAIL ,
-.Nm TAILQ_LAST ,
-.Nm TAILQ_NEXT ,
-.Nm TAILQ_PREV ,
-.Nm TAILQ_REMOVE ,
-.Nm TAILQ_SWAP
-.Nd implementations of singly-linked lists, singly-linked tail queues,
-lists and tail queues
-.Sh SYNOPSIS
-.In sys/queue.h
-.\"
-.Fn SLIST_EMPTY "SLIST_HEAD *head"
-.Fn SLIST_ENTRY "TYPE"
-.Fn SLIST_FIRST "SLIST_HEAD *head"
-.Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
-.Fn SLIST_FOREACH_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
-.Fn SLIST_HEAD "HEADNAME" "TYPE"
-.Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head"
-.Fn SLIST_INIT "SLIST_HEAD *head"
-.Fn SLIST_INSERT_AFTER "TYPE *listelm" "TYPE *elm" "SLIST_ENTRY NAME"
-.Fn SLIST_INSERT_HEAD "SLIST_HEAD *head" "TYPE *elm" "SLIST_ENTRY NAME"
-.Fn SLIST_NEXT "TYPE *elm" "SLIST_ENTRY NAME"
-.Fn SLIST_REMOVE_AFTER "TYPE *elm" "SLIST_ENTRY NAME"
-.Fn SLIST_REMOVE_HEAD "SLIST_HEAD *head" "SLIST_ENTRY NAME"
-.Fn SLIST_REMOVE "SLIST_HEAD *head" "TYPE *elm" "TYPE" "SLIST_ENTRY NAME"
-.Fn SLIST_SWAP "SLIST_HEAD *head1" "SLIST_HEAD *head2" "SLIST_ENTRY NAME"
-.\"
-.Fn STAILQ_CONCAT "STAILQ_HEAD *head1" "STAILQ_HEAD *head2"
-.Fn STAILQ_EMPTY "STAILQ_HEAD *head"
-.Fn STAILQ_ENTRY "TYPE"
-.Fn STAILQ_FIRST "STAILQ_HEAD *head"
-.Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
-.Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
-.Fn STAILQ_HEAD "HEADNAME" "TYPE"
-.Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head"
-.Fn STAILQ_INIT "STAILQ_HEAD *head"
-.Fn STAILQ_INSERT_AFTER "STAILQ_HEAD *head" "TYPE *listelm" "TYPE *elm" "STAILQ_ENTRY NAME"
-.Fn STAILQ_INSERT_HEAD "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
-.Fn STAILQ_INSERT_TAIL "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
-.Fn STAILQ_LAST "STAILQ_HEAD *head" "TYPE" "STAILQ_ENTRY NAME"
-.Fn STAILQ_NEXT "TYPE *elm" "STAILQ_ENTRY NAME"
-.Fn STAILQ_REMOVE_AFTER "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
-.Fn STAILQ_REMOVE_HEAD "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
-.Fn STAILQ_REMOVE "STAILQ_HEAD *head" "TYPE *elm" "TYPE" "STAILQ_ENTRY NAME"
-.Fn STAILQ_SWAP "STAILQ_HEAD *head1" "STAILQ_HEAD *head2" "STAILQ_ENTRY NAME"
-.\"
-.Fn LIST_EMPTY "LIST_HEAD *head"
-.Fn LIST_ENTRY "TYPE"
-.Fn LIST_FIRST "LIST_HEAD *head"
-.Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
-.Fn LIST_FOREACH_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
-.Fn LIST_HEAD "HEADNAME" "TYPE"
-.Fn LIST_HEAD_INITIALIZER "LIST_HEAD head"
-.Fn LIST_INIT "LIST_HEAD *head"
-.Fn LIST_INSERT_AFTER "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
-.Fn LIST_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
-.Fn LIST_INSERT_HEAD "LIST_HEAD *head" "TYPE *elm" "LIST_ENTRY NAME"
-.Fn LIST_NEXT "TYPE *elm" "LIST_ENTRY NAME"
-.Fn LIST_REMOVE "TYPE *elm" "LIST_ENTRY NAME"
-.Fn LIST_SWAP "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME"
-.\"
-.Fn TAILQ_CONCAT "TAILQ_HEAD *head1" "TAILQ_HEAD *head2" "TAILQ_ENTRY NAME"
-.Fn TAILQ_EMPTY "TAILQ_HEAD *head"
-.Fn TAILQ_ENTRY "TYPE"
-.Fn TAILQ_FIRST "TAILQ_HEAD *head"
-.Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
-.Fn TAILQ_FOREACH_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
-.Fn TAILQ_FOREACH_REVERSE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME"
-.Fn TAILQ_FOREACH_REVERSE_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
-.Fn TAILQ_HEAD "HEADNAME" "TYPE"
-.Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head"
-.Fn TAILQ_INIT "TAILQ_HEAD *head"
-.Fn TAILQ_INSERT_AFTER "TAILQ_HEAD *head" "TYPE *listelm" "TYPE *elm" "TAILQ_ENTRY NAME"
-.Fn TAILQ_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "TAILQ_ENTRY NAME"
-.Fn TAILQ_INSERT_HEAD "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
-.Fn TAILQ_INSERT_TAIL "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
-.Fn TAILQ_LAST "TAILQ_HEAD *head" "HEADNAME"
-.Fn TAILQ_NEXT "TYPE *elm" "TAILQ_ENTRY NAME"
-.Fn TAILQ_PREV "TYPE *elm" "HEADNAME" "TAILQ_ENTRY NAME"
-.Fn TAILQ_REMOVE "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
-.Fn TAILQ_SWAP "TAILQ_HEAD *head1" "TAILQ_HEAD *head2" "TYPE" "TAILQ_ENTRY NAME"
-.\"
-.Sh DESCRIPTION
-These macros define and operate on four types of data structures:
-singly-linked lists, singly-linked tail queues, lists, and tail queues.
-All four structures support the following functionality:
-.Bl -enum -compact -offset indent
-.It
-Insertion of a new entry at the head of the list.
-.It
-Insertion of a new entry after any element in the list.
-.It
-O(1) removal of an entry from the head of the list.
-.It
-Forward traversal through the list.
-.It
-Swawpping the contents of two lists.
-.El
-.Pp
-Singly-linked lists are the simplest of the four data structures
-and support only the above functionality.
-Singly-linked lists are ideal for applications with large datasets
-and few or no removals,
-or for implementing a LIFO queue.
-Singly-linked lists add the following functionality:
-.Bl -enum -compact -offset indent
-.It
-O(n) removal of any entry in the list.
-.El
-.Pp
-Singly-linked tail queues add the following functionality:
-.Bl -enum -compact -offset indent
-.It
-Entries can be added at the end of a list.
-.It
-O(n) removal of any entry in the list.
-.It
-They may be concatenated.
-.El
-However:
-.Bl -enum -compact -offset indent
-.It
-All list insertions must specify the head of the list.
-.It
-Each head entry requires two pointers rather than one.
-.It
-Code size is about 15% greater and operations run about 20% slower
-than singly-linked lists.
-.El
-.Pp
-Singly-linked tailqs are ideal for applications with large datasets and
-few or no removals,
-or for implementing a FIFO queue.
-.Pp
-All doubly linked types of data structures (lists and tail queues)
-additionally allow:
-.Bl -enum -compact -offset indent
-.It
-Insertion of a new entry before any element in the list.
-.It
-O(1) removal of any entry in the list.
-.El
-However:
-.Bl -enum -compact -offset indent
-.It
-Each element requires two pointers rather than one.
-.It
-Code size and execution time of operations (except for removal) is about
-twice that of the singly-linked data-structures.
-.El
-.Pp
-Linked lists are the simplest of the doubly linked data structures and support
-only the above functionality over singly-linked lists.
-.Pp
-Tail queues add the following functionality:
-.Bl -enum -compact -offset indent
-.It
-Entries can be added at the end of a list.
-.It
-They may be traversed backwards, from tail to head.
-.It
-They may be concatenated.
-.El
-However:
-.Bl -enum -compact -offset indent
-.It
-All list insertions and removals must specify the head of the list.
-.It
-Each head entry requires two pointers rather than one.
-.It
-Code size is about 15% greater and operations run about 20% slower
-than singly-linked lists.
-.El
-.Pp
-In the macro definitions,
-.Fa TYPE
-is the name of a user defined structure,
-that must contain a field of type
-.Li SLIST_ENTRY ,
-.Li STAILQ_ENTRY ,
-.Li LIST_ENTRY ,
-or
-.Li TAILQ_ENTRY ,
-named
-.Fa NAME .
-The argument
-.Fa HEADNAME
-is the name of a user defined structure that must be declared
-using the macros
-.Li SLIST_HEAD ,
-.Li STAILQ_HEAD ,
-.Li LIST_HEAD ,
-or
-.Li TAILQ_HEAD .
-See the examples below for further explanation of how these
-macros are used.
-.Sh SINGLY-LINKED LISTS
-A singly-linked list is headed by a structure defined by the
-.Nm SLIST_HEAD
-macro.
-This structure contains a single pointer to the first element
-on the list.
-The elements are singly linked for minimum space and pointer manipulation
-overhead at the expense of O(n) removal for arbitrary elements.
-New elements can be added to the list after an existing element or
-at the head of the list.
-An
-.Fa SLIST_HEAD
-structure is declared as follows:
-.Bd -literal -offset indent
-SLIST_HEAD(HEADNAME, TYPE) head;
-.Ed
-.Pp
-where
-.Fa HEADNAME
-is the name of the structure to be defined, and
-.Fa TYPE
-is the type of the elements to be linked into the list.
-A pointer to the head of the list can later be declared as:
-.Bd -literal -offset indent
-struct HEADNAME *headp;
-.Ed
-.Pp
-(The names
-.Li head
-and
-.Li headp
-are user selectable.)
-.Pp
-The macro
-.Nm SLIST_HEAD_INITIALIZER
-evaluates to an initializer for the list
-.Fa head .
-.Pp
-The macro
-.Nm SLIST_EMPTY
-evaluates to true if there are no elements in the list.
-.Pp
-The macro
-.Nm SLIST_ENTRY
-declares a structure that connects the elements in
-the list.
-.Pp
-The macro
-.Nm SLIST_FIRST
-returns the first element in the list or NULL if the list is empty.
-.Pp
-The macro
-.Nm SLIST_FOREACH
-traverses the list referenced by
-.Fa head
-in the forward direction, assigning each element in
-turn to
-.Fa var .
-.Pp
-The macro
-.Nm SLIST_FOREACH_SAFE
-traverses the list referenced by
-.Fa head
-in the forward direction, assigning each element in
-turn to
-.Fa var .
-However, unlike
-.Fn SLIST_FOREACH
-here it is permitted to both remove
-.Fa var
-as well as free it from within the loop safely without interfering with the
-traversal.
-.Pp
-The macro
-.Nm SLIST_INIT
-initializes the list referenced by
-.Fa head .
-.Pp
-The macro
-.Nm SLIST_INSERT_HEAD
-inserts the new element
-.Fa elm
-at the head of the list.
-.Pp
-The macro
-.Nm SLIST_INSERT_AFTER
-inserts the new element
-.Fa elm
-after the element
-.Fa listelm .
-.Pp
-The macro
-.Nm SLIST_NEXT
-returns the next element in the list.
-.Pp
-The macro
-.Nm SLIST_REMOVE_AFTER
-removes the element after
-.Fa elm
-from the list. Unlike
-.Fa SLIST_REMOVE ,
-this macro does not traverse the entire list.
-.Pp
-The macro
-.Nm SLIST_REMOVE_HEAD
-removes the element
-.Fa elm
-from the head of the list.
-For optimum efficiency,
-elements being removed from the head of the list should explicitly use
-this macro instead of the generic
-.Fa SLIST_REMOVE
-macro.
-.Pp
-The macro
-.Nm SLIST_REMOVE
-removes the element
-.Fa elm
-from the list.
-.Pp
-The macro
-.Nm SLIST_SWAP
-swaps the contents of
-.Fa head1
-and
-.Fa head2 .
-.Sh SINGLY-LINKED LIST EXAMPLE
-.Bd -literal
-SLIST_HEAD(slisthead, entry) head =
- SLIST_HEAD_INITIALIZER(head);
-struct slisthead *headp; /* Singly-linked List head. */
-struct entry {
- ...
- SLIST_ENTRY(entry) entries; /* Singly-linked List. */
- ...
-} *n1, *n2, *n3, *np;
-
-SLIST_INIT(&head); /* Initialize the list. */
-
-n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
-SLIST_INSERT_HEAD(&head, n1, entries);
-
-n2 = malloc(sizeof(struct entry)); /* Insert after. */
-SLIST_INSERT_AFTER(n1, n2, entries);
-
-SLIST_REMOVE(&head, n2, entry, entries);/* Deletion. */
-free(n2);
-
-n3 = SLIST_FIRST(&head);
-SLIST_REMOVE_HEAD(&head, entries); /* Deletion from the head. */
-free(n3);
- /* Forward traversal. */
-SLIST_FOREACH(np, &head, entries)
- np-> ...
- /* Safe forward traversal. */
-SLIST_FOREACH_SAFE(np, &head, entries, np_temp) {
- np->do_stuff();
- ...
- SLIST_REMOVE(&head, np, entry, entries);
- free(np);
-}
-
-while (!SLIST_EMPTY(&head)) { /* List Deletion. */
- n1 = SLIST_FIRST(&head);
- SLIST_REMOVE_HEAD(&head, entries);
- free(n1);
-}
-.Ed
-.Sh SINGLY-LINKED TAIL QUEUES
-A singly-linked tail queue is headed by a structure defined by the
-.Nm STAILQ_HEAD
-macro.
-This structure contains a pair of pointers,
-one to the first element in the tail queue and the other to
-the last element in the tail queue.
-The elements are singly linked for minimum space and pointer
-manipulation overhead at the expense of O(n) removal for arbitrary
-elements.
-New elements can be added to the tail queue after an existing element,
-at the head of the tail queue, or at the end of the tail queue.
-A
-.Fa STAILQ_HEAD
-structure is declared as follows:
-.Bd -literal -offset indent
-STAILQ_HEAD(HEADNAME, TYPE) head;
-.Ed
-.Pp
-where
-.Li HEADNAME
-is the name of the structure to be defined, and
-.Li TYPE
-is the type of the elements to be linked into the tail queue.
-A pointer to the head of the tail queue can later be declared as:
-.Bd -literal -offset indent
-struct HEADNAME *headp;
-.Ed
-.Pp
-(The names
-.Li head
-and
-.Li headp
-are user selectable.)
-.Pp
-The macro
-.Nm STAILQ_HEAD_INITIALIZER
-evaluates to an initializer for the tail queue
-.Fa head .
-.Pp
-The macro
-.Nm STAILQ_CONCAT
-concatenates the tail queue headed by
-.Fa head2
-onto the end of the one headed by
-.Fa head1
-removing all entries from the former.
-.Pp
-The macro
-.Nm STAILQ_EMPTY
-evaluates to true if there are no items on the tail queue.
-.Pp
-The macro
-.Nm STAILQ_ENTRY
-declares a structure that connects the elements in
-the tail queue.
-.Pp
-The macro
-.Nm STAILQ_FIRST
-returns the first item on the tail queue or NULL if the tail queue
-is empty.
-.Pp
-The macro
-.Nm STAILQ_FOREACH
-traverses the tail queue referenced by
-.Fa head
-in the forward direction, assigning each element
-in turn to
-.Fa var .
-.Pp
-The macro
-.Nm STAILQ_FOREACH_SAFE
-traverses the tail queue referenced by
-.Fa head
-in the forward direction, assigning each element
-in turn to
-.Fa var .
-However, unlike
-.Fn STAILQ_FOREACH
-here it is permitted to both remove
-.Fa var
-as well as free it from within the loop safely without interfering with the
-traversal.
-.Pp
-The macro
-.Nm STAILQ_INIT
-initializes the tail queue referenced by
-.Fa head .
-.Pp
-The macro
-.Nm STAILQ_INSERT_HEAD
-inserts the new element
-.Fa elm
-at the head of the tail queue.
-.Pp
-The macro
-.Nm STAILQ_INSERT_TAIL
-inserts the new element
-.Fa elm
-at the end of the tail queue.
-.Pp
-The macro
-.Nm STAILQ_INSERT_AFTER
-inserts the new element
-.Fa elm
-after the element
-.Fa listelm .
-.Pp
-The macro
-.Nm STAILQ_LAST
-returns the last item on the tail queue.
-If the tail queue is empty the return value is
-.Dv NULL .
-.Pp
-The macro
-.Nm STAILQ_NEXT
-returns the next item on the tail queue, or NULL this item is the last.
-.Pp
-The macro
-.Nm STAILQ_REMOVE_AFTER
-removes the element after
-.Fa elm
-from the tail queue. Unlike
-.Fa STAILQ_REMOVE ,
-this macro does not traverse the entire tail queue.
-.Pp
-The macro
-.Nm STAILQ_REMOVE_HEAD
-removes the element at the head of the tail queue.
-For optimum efficiency,
-elements being removed from the head of the tail queue should
-use this macro explicitly rather than the generic
-.Fa STAILQ_REMOVE
-macro.
-.Pp
-The macro
-.Nm STAILQ_REMOVE
-removes the element
-.Fa elm
-from the tail queue.
-.Pp
-The macro
-.Nm STAILQ_SWAP
-swaps the contents of
-.Fa head1
-and
-.Fa head2 .
-.Sh SINGLY-LINKED TAIL QUEUE EXAMPLE
-.Bd -literal
-STAILQ_HEAD(stailhead, entry) head =
- STAILQ_HEAD_INITIALIZER(head);
-struct stailhead *headp; /* Singly-linked tail queue head. */
-struct entry {
- ...
- STAILQ_ENTRY(entry) entries; /* Tail queue. */
- ...
-} *n1, *n2, *n3, *np;
-
-STAILQ_INIT(&head); /* Initialize the queue. */
-
-n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
-STAILQ_INSERT_HEAD(&head, n1, entries);
-
-n1 = malloc(sizeof(struct entry)); /* Insert at the tail. */
-STAILQ_INSERT_TAIL(&head, n1, entries);
-
-n2 = malloc(sizeof(struct entry)); /* Insert after. */
-STAILQ_INSERT_AFTER(&head, n1, n2, entries);
- /* Deletion. */
-STAILQ_REMOVE(&head, n2, entry, entries);
-free(n2);
- /* Deletion from the head. */
-n3 = STAILQ_FIRST(&head);
-STAILQ_REMOVE_HEAD(&head, entries);
-free(n3);
- /* Forward traversal. */
-STAILQ_FOREACH(np, &head, entries)
- np-> ...
- /* Safe forward traversal. */
-STAILQ_FOREACH_SAFE(np, &head, entries, np_temp) {
- np->do_stuff();
- ...
- STAILQ_REMOVE(&head, np, entry, entries);
- free(np);
-}
- /* TailQ Deletion. */
-while (!STAILQ_EMPTY(&head)) {
- n1 = STAILQ_FIRST(&head);
- STAILQ_REMOVE_HEAD(&head, entries);
- free(n1);
-}
- /* Faster TailQ Deletion. */
-n1 = STAILQ_FIRST(&head);
-while (n1 != NULL) {
- n2 = STAILQ_NEXT(n1, entries);
- free(n1);
- n1 = n2;
-}
-STAILQ_INIT(&head);
-.Ed
-.Sh LISTS
-A list is headed by a structure defined by the
-.Nm LIST_HEAD
-macro.
-This structure contains a single pointer to the first element
-on the list.
-The elements are doubly linked so that an arbitrary element can be
-removed without traversing the list.
-New elements can be added to the list after an existing element,
-before an existing element, or at the head of the list.
-A
-.Fa LIST_HEAD
-structure is declared as follows:
-.Bd -literal -offset indent
-LIST_HEAD(HEADNAME, TYPE) head;
-.Ed
-.Pp
-where
-.Fa HEADNAME
-is the name of the structure to be defined, and
-.Fa TYPE
-is the type of the elements to be linked into the list.
-A pointer to the head of the list can later be declared as:
-.Bd -literal -offset indent
-struct HEADNAME *headp;
-.Ed
-.Pp
-(The names
-.Li head
-and
-.Li headp
-are user selectable.)
-.Pp
-The macro
-.Nm LIST_HEAD_INITIALIZER
-evaluates to an initializer for the list
-.Fa head .
-.Pp
-The macro
-.Nm LIST_EMPTY
-evaluates to true if there are no elements in the list.
-.Pp
-The macro
-.Nm LIST_ENTRY
-declares a structure that connects the elements in
-the list.
-.Pp
-The macro
-.Nm LIST_FIRST
-returns the first element in the list or NULL if the list
-is empty.
-.Pp
-The macro
-.Nm LIST_FOREACH
-traverses the list referenced by
-.Fa head
-in the forward direction, assigning each element in turn to
-.Fa var .
-.Pp
-The macro
-.Nm LIST_FOREACH_SAFE
-traverses the list referenced by
-.Fa head
-in the forward direction, assigning each element in turn to
-.Fa var .
-However, unlike
-.Fn LIST_FOREACH
-here it is permitted to both remove
-.Fa var
-as well as free it from within the loop safely without interfering with the
-traversal.
-.Pp
-The macro
-.Nm LIST_INIT
-initializes the list referenced by
-.Fa head .
-.Pp
-The macro
-.Nm LIST_INSERT_HEAD
-inserts the new element
-.Fa elm
-at the head of the list.
-.Pp
-The macro
-.Nm LIST_INSERT_AFTER
-inserts the new element
-.Fa elm
-after the element
-.Fa listelm .
-.Pp
-The macro
-.Nm LIST_INSERT_BEFORE
-inserts the new element
-.Fa elm
-before the element
-.Fa listelm .
-.Pp
-The macro
-.Nm LIST_NEXT
-returns the next element in the list, or NULL if this is the last.
-.Pp
-The macro
-.Nm LIST_REMOVE
-removes the element
-.Fa elm
-from the list.
-.Pp
-The macro
-.Nm LIST_SWAP
-swaps the contents of
-.Fa head1
-and
-.Fa head2 .
-.Sh LIST EXAMPLE
-.Bd -literal
-LIST_HEAD(listhead, entry) head =
- LIST_HEAD_INITIALIZER(head);
-struct listhead *headp; /* List head. */
-struct entry {
- ...
- LIST_ENTRY(entry) entries; /* List. */
- ...
-} *n1, *n2, *n3, *np, *np_temp;
-
-LIST_INIT(&head); /* Initialize the list. */
-
-n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
-LIST_INSERT_HEAD(&head, n1, entries);
-
-n2 = malloc(sizeof(struct entry)); /* Insert after. */
-LIST_INSERT_AFTER(n1, n2, entries);
-
-n3 = malloc(sizeof(struct entry)); /* Insert before. */
-LIST_INSERT_BEFORE(n2, n3, entries);
-
-LIST_REMOVE(n2, entries); /* Deletion. */
-free(n2);
- /* Forward traversal. */
-LIST_FOREACH(np, &head, entries)
- np-> ...
-
- /* Safe forward traversal. */
-LIST_FOREACH_SAFE(np, &head, entries, np_temp) {
- np->do_stuff();
- ...
- LIST_REMOVE(np, entries);
- free(np);
-}
-
-while (!LIST_EMPTY(&head)) { /* List Deletion. */
- n1 = LIST_FIRST(&head);
- LIST_REMOVE(n1, entries);
- free(n1);
-}
-
-n1 = LIST_FIRST(&head); /* Faster List Deletion. */
-while (n1 != NULL) {
- n2 = LIST_NEXT(n1, entries);
- free(n1);
- n1 = n2;
-}
-LIST_INIT(&head);
-.Ed
-.Sh TAIL QUEUES
-A tail queue is headed by a structure defined by the
-.Nm TAILQ_HEAD
-macro.
-This structure contains a pair of pointers,
-one to the first element in the tail queue and the other to
-the last element in the tail queue.
-The elements are doubly linked so that an arbitrary element can be
-removed without traversing the tail queue.
-New elements can be added to the tail queue after an existing element,
-before an existing element, at the head of the tail queue,
-or at the end of the tail queue.
-A
-.Fa TAILQ_HEAD
-structure is declared as follows:
-.Bd -literal -offset indent
-TAILQ_HEAD(HEADNAME, TYPE) head;
-.Ed
-.Pp
-where
-.Li HEADNAME
-is the name of the structure to be defined, and
-.Li TYPE
-is the type of the elements to be linked into the tail queue.
-A pointer to the head of the tail queue can later be declared as:
-.Bd -literal -offset indent
-struct HEADNAME *headp;
-.Ed
-.Pp
-(The names
-.Li head
-and
-.Li headp
-are user selectable.)
-.Pp
-The macro
-.Nm TAILQ_HEAD_INITIALIZER
-evaluates to an initializer for the tail queue
-.Fa head .
-.Pp
-The macro
-.Nm TAILQ_CONCAT
-concatenates the tail queue headed by
-.Fa head2
-onto the end of the one headed by
-.Fa head1
-removing all entries from the former.
-.Pp
-The macro
-.Nm TAILQ_EMPTY
-evaluates to true if there are no items on the tail queue.
-.Pp
-The macro
-.Nm TAILQ_ENTRY
-declares a structure that connects the elements in
-the tail queue.
-.Pp
-The macro
-.Nm TAILQ_FIRST
-returns the first item on the tail queue or NULL if the tail queue
-is empty.
-.Pp
-The macro
-.Nm TAILQ_FOREACH
-traverses the tail queue referenced by
-.Fa head
-in the forward direction, assigning each element in turn to
-.Fa var .
-.Fa var
-is set to
-.Dv NULL
-if the loop completes normally, or if there were no elements.
-.Pp
-The macro
-.Nm TAILQ_FOREACH_REVERSE
-traverses the tail queue referenced by
-.Fa head
-in the reverse direction, assigning each element in turn to
-.Fa var .
-.Pp
-The macros
-.Nm TAILQ_FOREACH_SAFE
-and
-.Nm TAILQ_FOREACH_REVERSE_SAFE
-traverse the list referenced by
-.Fa head
-in the forward or reverse direction respectively,
-assigning each element in turn to
-.Fa var .
-However, unlike their unsafe counterparts,
-.Nm TAILQ_FOREACH
-and
-.Nm TAILQ_FOREACH_REVERSE
-permit to both remove
-.Fa var
-as well as free it from within the loop safely without interfering with the
-traversal.
-.Pp
-The macro
-.Nm TAILQ_INIT
-initializes the tail queue referenced by
-.Fa head .
-.Pp
-The macro
-.Nm TAILQ_INSERT_HEAD
-inserts the new element
-.Fa elm
-at the head of the tail queue.
-.Pp
-The macro
-.Nm TAILQ_INSERT_TAIL
-inserts the new element
-.Fa elm
-at the end of the tail queue.
-.Pp
-The macro
-.Nm TAILQ_INSERT_AFTER
-inserts the new element
-.Fa elm
-after the element
-.Fa listelm .
-.Pp
-The macro
-.Nm TAILQ_INSERT_BEFORE
-inserts the new element
-.Fa elm
-before the element
-.Fa listelm .
-.Pp
-The macro
-.Nm TAILQ_LAST
-returns the last item on the tail queue.
-If the tail queue is empty the return value is
-.Dv NULL .
-.Pp
-The macro
-.Nm TAILQ_NEXT
-returns the next item on the tail queue, or NULL if this item is the last.
-.Pp
-The macro
-.Nm TAILQ_PREV
-returns the previous item on the tail queue, or NULL if this item
-is the first.
-.Pp
-The macro
-.Nm TAILQ_REMOVE
-removes the element
-.Fa elm
-from the tail queue.
-.Pp
-The macro
-.Nm TAILQ_SWAP
-swaps the contents of
-.Fa head1
-and
-.Fa head2 .
-.Sh TAIL QUEUE EXAMPLE
-.Bd -literal
-TAILQ_HEAD(tailhead, entry) head =
- TAILQ_HEAD_INITIALIZER(head);
-struct tailhead *headp; /* Tail queue head. */
-struct entry {
- ...
- TAILQ_ENTRY(entry) entries; /* Tail queue. */
- ...
-} *n1, *n2, *n3, *np;
-
-TAILQ_INIT(&head); /* Initialize the queue. */
-
-n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
-TAILQ_INSERT_HEAD(&head, n1, entries);
-
-n1 = malloc(sizeof(struct entry)); /* Insert at the tail. */
-TAILQ_INSERT_TAIL(&head, n1, entries);
-
-n2 = malloc(sizeof(struct entry)); /* Insert after. */
-TAILQ_INSERT_AFTER(&head, n1, n2, entries);
-
-n3 = malloc(sizeof(struct entry)); /* Insert before. */
-TAILQ_INSERT_BEFORE(n2, n3, entries);
-
-TAILQ_REMOVE(&head, n2, entries); /* Deletion. */
-free(n2);
- /* Forward traversal. */
-TAILQ_FOREACH(np, &head, entries)
- np-> ...
- /* Safe forward traversal. */
-TAILQ_FOREACH_SAFE(np, &head, entries, np_temp) {
- np->do_stuff();
- ...
- TAILQ_REMOVE(&head, np, entries);
- free(np);
-}
- /* Reverse traversal. */
-TAILQ_FOREACH_REVERSE(np, &head, tailhead, entries)
- np-> ...
- /* TailQ Deletion. */
-while (!TAILQ_EMPTY(&head)) {
- n1 = TAILQ_FIRST(&head);
- TAILQ_REMOVE(&head, n1, entries);
- free(n1);
-}
- /* Faster TailQ Deletion. */
-n1 = TAILQ_FIRST(&head);
-while (n1 != NULL) {
- n2 = TAILQ_NEXT(n1, entries);
- free(n1);
- n1 = n2;
-}
-TAILQ_INIT(&head);
-.Ed
-.Sh SEE ALSO
-.Xr tree 3
-.Sh HISTORY
-The
-.Nm queue
-functions first appeared in
-.Bx 4.4 .
+++ /dev/null
-#!/usr/bin/perl -p
-#
-# This script is part of the Xen build system. It has a very
-# permissive licence to avoid complicating the licence of the
-# generated header file and to allow this seddery to be reused by
-# other projects.
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this individual file (the "Software"), to deal
-# in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute,
-# sublicense, and/or sell copies of the Software, and to permit
-# persons to whom the Software is furnished to do so, subject to the
-# following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
-# Copyright (C) 2011 Citrix Ltd
-
-our $namespace, $ucnamespace;
-
-BEGIN {
- die unless @ARGV;
- $namespace = pop @ARGV;
- $namespace =~ s/^--prefix=// or die;
- $ucnamespace = uc $namespace;
-
- print <<END or die $!;
-/*
- * DO NOT EDIT THIS FILE
- *
- * Generated automatically by bsd-sys-queue-h-seddery to
- * - introduce ${ucnamespace}_ and ${namespace}_ namespace prefixes
- * - turn "struct type" into "type" so that type arguments
- * to the macros are type names not struct tags
- * - remove the reference to sys/cdefs.h, which is not needed
- *
- * The purpose of this seddery is to allow the resulting file to be
- * freely included by software which might also want to include other
- * list macros; to make it usable when struct tags are not being used
- * or not known; to make it more portable.
- */
-END
-}
-
-s/\b( _SYS_QUEUE |
- SLIST | LIST | STAILQ | TAILQ | QUEUE
- )/${ucnamespace}_$1/xg;
-
-s/\b( TRACEBUF | TRASHIT |
- QMD_
- )/${ucnamespace}__$1/xg;
-
-s/\b(
- qm_
- )/${namespace}__$1/xg;
-
-s/\b struct \s+ type \b/type/xg;
-
-s,^\#include.*sys/cdefs.*,/* $& */,xg;
-
-s/\b( NULL )/0/xg;
+++ /dev/null
-/*-
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)queue.h 8.5 (Berkeley) 8/20/94
- * $FreeBSD$
- */
-
-#ifndef _SYS_QUEUE_H_
-#define _SYS_QUEUE_H_
-
-#include <sys/cdefs.h>
-
-/*
- * This file defines four types of data structures: singly-linked lists,
- * singly-linked tail queues, lists and tail queues.
- *
- * A singly-linked list is headed by a single forward pointer. The elements
- * are singly linked for minimum space and pointer manipulation overhead at
- * the expense of O(n) removal for arbitrary elements. New elements can be
- * added to the list after an existing element or at the head of the list.
- * Elements being removed from the head of the list should use the explicit
- * macro for this purpose for optimum efficiency. A singly-linked list may
- * only be traversed in the forward direction. Singly-linked lists are ideal
- * for applications with large datasets and few or no removals or for
- * implementing a LIFO queue.
- *
- * A singly-linked tail queue is headed by a pair of pointers, one to the
- * head of the list and the other to the tail of the list. The elements are
- * singly linked for minimum space and pointer manipulation overhead at the
- * expense of O(n) removal for arbitrary elements. New elements can be added
- * to the list after an existing element, at the head of the list, or at the
- * end of the list. Elements being removed from the head of the tail queue
- * should use the explicit macro for this purpose for optimum efficiency.
- * A singly-linked tail queue may only be traversed in the forward direction.
- * Singly-linked tail queues are ideal for applications with large datasets
- * and few or no removals or for implementing a FIFO queue.
- *
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may only be traversed in the forward direction.
- *
- * A tail queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or
- * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may be traversed in either direction.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- *
- *
- * SLIST LIST STAILQ TAILQ
- * _HEAD + + + +
- * _HEAD_INITIALIZER + + + +
- * _ENTRY + + + +
- * _INIT + + + +
- * _EMPTY + + + +
- * _FIRST + + + +
- * _NEXT + + + +
- * _PREV - - - +
- * _LAST - - + +
- * _FOREACH + + + +
- * _FOREACH_SAFE + + + +
- * _FOREACH_REVERSE - - - +
- * _FOREACH_REVERSE_SAFE - - - +
- * _INSERT_HEAD + + + +
- * _INSERT_BEFORE - + - +
- * _INSERT_AFTER + + + +
- * _INSERT_TAIL - - + +
- * _CONCAT - - + +
- * _REMOVE_AFTER + - + -
- * _REMOVE_HEAD + - + -
- * _REMOVE + + + +
- * _SWAP + + + +
- *
- */
-#ifdef QUEUE_MACRO_DEBUG
-/* Store the last 2 places the queue element or head was altered */
-struct qm_trace {
- char * lastfile;
- int lastline;
- char * prevfile;
- int prevline;
-};
-
-#define TRACEBUF struct qm_trace trace;
-#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
-#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
-
-#define QMD_TRACE_HEAD(head) do { \
- (head)->trace.prevline = (head)->trace.lastline; \
- (head)->trace.prevfile = (head)->trace.lastfile; \
- (head)->trace.lastline = __LINE__; \
- (head)->trace.lastfile = __FILE__; \
-} while (0)
-
-#define QMD_TRACE_ELEM(elem) do { \
- (elem)->trace.prevline = (elem)->trace.lastline; \
- (elem)->trace.prevfile = (elem)->trace.lastfile; \
- (elem)->trace.lastline = __LINE__; \
- (elem)->trace.lastfile = __FILE__; \
-} while (0)
-
-#else
-#define QMD_TRACE_ELEM(elem)
-#define QMD_TRACE_HEAD(head)
-#define QMD_SAVELINK(name, link)
-#define TRACEBUF
-#define TRASHIT(x)
-#endif /* QUEUE_MACRO_DEBUG */
-
-/*
- * Singly-linked List declarations.
- */
-#define SLIST_HEAD(name, type) \
-struct name { \
- struct type *slh_first; /* first element */ \
-}
-
-#define SLIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#define SLIST_ENTRY(type) \
-struct { \
- struct type *sle_next; /* next element */ \
-}
-
-/*
- * Singly-linked List functions.
- */
-#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
-
-#define SLIST_FIRST(head) ((head)->slh_first)
-
-#define SLIST_FOREACH(var, head, field) \
- for ((var) = SLIST_FIRST((head)); \
- (var); \
- (var) = SLIST_NEXT((var), field))
-
-#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = SLIST_FIRST((head)); \
- (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
- for ((varp) = &SLIST_FIRST((head)); \
- ((var) = *(varp)) != NULL; \
- (varp) = &SLIST_NEXT((var), field))
-
-#define SLIST_INIT(head) do { \
- SLIST_FIRST((head)) = NULL; \
-} while (0)
-
-#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
- SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
- SLIST_NEXT((slistelm), field) = (elm); \
-} while (0)
-
-#define SLIST_INSERT_HEAD(head, elm, field) do { \
- SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
- SLIST_FIRST((head)) = (elm); \
-} while (0)
-
-#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
-
-#define SLIST_REMOVE(head, elm, type, field) do { \
- QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
- if (SLIST_FIRST((head)) == (elm)) { \
- SLIST_REMOVE_HEAD((head), field); \
- } \
- else { \
- struct type *curelm = SLIST_FIRST((head)); \
- while (SLIST_NEXT(curelm, field) != (elm)) \
- curelm = SLIST_NEXT(curelm, field); \
- SLIST_REMOVE_AFTER(curelm, field); \
- } \
- TRASHIT(*oldnext); \
-} while (0)
-
-#define SLIST_REMOVE_AFTER(elm, field) do { \
- SLIST_NEXT(elm, field) = \
- SLIST_NEXT(SLIST_NEXT(elm, field), field); \
-} while (0)
-
-#define SLIST_REMOVE_HEAD(head, field) do { \
- SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
-} while (0)
-
-#define SLIST_SWAP(head1, head2, type) do { \
- struct type *swap_first = SLIST_FIRST(head1); \
- SLIST_FIRST(head1) = SLIST_FIRST(head2); \
- SLIST_FIRST(head2) = swap_first; \
-} while (0)
-
-/*
- * Singly-linked Tail queue declarations.
- */
-#define STAILQ_HEAD(name, type) \
-struct name { \
- struct type *stqh_first;/* first element */ \
- struct type **stqh_last;/* addr of last next element */ \
-}
-
-#define STAILQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).stqh_first }
-
-#define STAILQ_ENTRY(type) \
-struct { \
- struct type *stqe_next; /* next element */ \
-}
-
-/*
- * Singly-linked Tail queue functions.
- */
-#define STAILQ_CONCAT(head1, head2) do { \
- if (!STAILQ_EMPTY((head2))) { \
- *(head1)->stqh_last = (head2)->stqh_first; \
- (head1)->stqh_last = (head2)->stqh_last; \
- STAILQ_INIT((head2)); \
- } \
-} while (0)
-
-#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
-
-#define STAILQ_FIRST(head) ((head)->stqh_first)
-
-#define STAILQ_FOREACH(var, head, field) \
- for((var) = STAILQ_FIRST((head)); \
- (var); \
- (var) = STAILQ_NEXT((var), field))
-
-
-#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = STAILQ_FIRST((head)); \
- (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define STAILQ_INIT(head) do { \
- STAILQ_FIRST((head)) = NULL; \
- (head)->stqh_last = &STAILQ_FIRST((head)); \
-} while (0)
-
-#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
- if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
- (head)->stqh_last = &STAILQ_NEXT((elm), field); \
- STAILQ_NEXT((tqelm), field) = (elm); \
-} while (0)
-
-#define STAILQ_INSERT_HEAD(head, elm, field) do { \
- if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
- (head)->stqh_last = &STAILQ_NEXT((elm), field); \
- STAILQ_FIRST((head)) = (elm); \
-} while (0)
-
-#define STAILQ_INSERT_TAIL(head, elm, field) do { \
- STAILQ_NEXT((elm), field) = NULL; \
- *(head)->stqh_last = (elm); \
- (head)->stqh_last = &STAILQ_NEXT((elm), field); \
-} while (0)
-
-#define STAILQ_LAST(head, type, field) \
- (STAILQ_EMPTY((head)) ? \
- NULL : \
- ((struct type *)(void *) \
- ((char *)((head)->stqh_last) - __offsetof(struct type, field))))
-
-#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
-
-#define STAILQ_REMOVE(head, elm, type, field) do { \
- QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
- if (STAILQ_FIRST((head)) == (elm)) { \
- STAILQ_REMOVE_HEAD((head), field); \
- } \
- else { \
- struct type *curelm = STAILQ_FIRST((head)); \
- while (STAILQ_NEXT(curelm, field) != (elm)) \
- curelm = STAILQ_NEXT(curelm, field); \
- STAILQ_REMOVE_AFTER(head, curelm, field); \
- } \
- TRASHIT(*oldnext); \
-} while (0)
-
-#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
- if ((STAILQ_NEXT(elm, field) = \
- STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
- (head)->stqh_last = &STAILQ_NEXT((elm), field); \
-} while (0)
-
-#define STAILQ_REMOVE_HEAD(head, field) do { \
- if ((STAILQ_FIRST((head)) = \
- STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
- (head)->stqh_last = &STAILQ_FIRST((head)); \
-} while (0)
-
-#define STAILQ_SWAP(head1, head2, type) do { \
- struct type *swap_first = STAILQ_FIRST(head1); \
- struct type **swap_last = (head1)->stqh_last; \
- STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
- (head1)->stqh_last = (head2)->stqh_last; \
- STAILQ_FIRST(head2) = swap_first; \
- (head2)->stqh_last = swap_last; \
- if (STAILQ_EMPTY(head1)) \
- (head1)->stqh_last = &STAILQ_FIRST(head1); \
- if (STAILQ_EMPTY(head2)) \
- (head2)->stqh_last = &STAILQ_FIRST(head2); \
-} while (0)
-
-
-/*
- * List declarations.
- */
-#define LIST_HEAD(name, type) \
-struct name { \
- struct type *lh_first; /* first element */ \
-}
-
-#define LIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#define LIST_ENTRY(type) \
-struct { \
- struct type *le_next; /* next element */ \
- struct type **le_prev; /* address of previous next element */ \
-}
-
-/*
- * List functions.
- */
-
-#if (defined(_KERNEL) && defined(INVARIANTS))
-#define QMD_LIST_CHECK_HEAD(head, field) do { \
- if (LIST_FIRST((head)) != NULL && \
- LIST_FIRST((head))->field.le_prev != \
- &LIST_FIRST((head))) \
- panic("Bad list head %p first->prev != head", (head)); \
-} while (0)
-
-#define QMD_LIST_CHECK_NEXT(elm, field) do { \
- if (LIST_NEXT((elm), field) != NULL && \
- LIST_NEXT((elm), field)->field.le_prev != \
- &((elm)->field.le_next)) \
- panic("Bad link elm %p next->prev != elm", (elm)); \
-} while (0)
-
-#define QMD_LIST_CHECK_PREV(elm, field) do { \
- if (*(elm)->field.le_prev != (elm)) \
- panic("Bad link elm %p prev->next != elm", (elm)); \
-} while (0)
-#else
-#define QMD_LIST_CHECK_HEAD(head, field)
-#define QMD_LIST_CHECK_NEXT(elm, field)
-#define QMD_LIST_CHECK_PREV(elm, field)
-#endif /* (_KERNEL && INVARIANTS) */
-
-#define LIST_EMPTY(head) ((head)->lh_first == NULL)
-
-#define LIST_FIRST(head) ((head)->lh_first)
-
-#define LIST_FOREACH(var, head, field) \
- for ((var) = LIST_FIRST((head)); \
- (var); \
- (var) = LIST_NEXT((var), field))
-
-#define LIST_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = LIST_FIRST((head)); \
- (var) && ((tvar) = LIST_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define LIST_INIT(head) do { \
- LIST_FIRST((head)) = NULL; \
-} while (0)
-
-#define LIST_INSERT_AFTER(listelm, elm, field) do { \
- QMD_LIST_CHECK_NEXT(listelm, field); \
- if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
- LIST_NEXT((listelm), field)->field.le_prev = \
- &LIST_NEXT((elm), field); \
- LIST_NEXT((listelm), field) = (elm); \
- (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
-} while (0)
-
-#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
- QMD_LIST_CHECK_PREV(listelm, field); \
- (elm)->field.le_prev = (listelm)->field.le_prev; \
- LIST_NEXT((elm), field) = (listelm); \
- *(listelm)->field.le_prev = (elm); \
- (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
-} while (0)
-
-#define LIST_INSERT_HEAD(head, elm, field) do { \
- QMD_LIST_CHECK_HEAD((head), field); \
- if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
- LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
- LIST_FIRST((head)) = (elm); \
- (elm)->field.le_prev = &LIST_FIRST((head)); \
-} while (0)
-
-#define LIST_NEXT(elm, field) ((elm)->field.le_next)
-
-#define LIST_REMOVE(elm, field) do { \
- QMD_SAVELINK(oldnext, (elm)->field.le_next); \
- QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
- QMD_LIST_CHECK_NEXT(elm, field); \
- QMD_LIST_CHECK_PREV(elm, field); \
- if (LIST_NEXT((elm), field) != NULL) \
- LIST_NEXT((elm), field)->field.le_prev = \
- (elm)->field.le_prev; \
- *(elm)->field.le_prev = LIST_NEXT((elm), field); \
- TRASHIT(*oldnext); \
- TRASHIT(*oldprev); \
-} while (0)
-
-#define LIST_SWAP(head1, head2, type, field) do { \
- struct type *swap_tmp = LIST_FIRST((head1)); \
- LIST_FIRST((head1)) = LIST_FIRST((head2)); \
- LIST_FIRST((head2)) = swap_tmp; \
- if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
- swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
- if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
- swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
-} while (0)
-
-/*
- * Tail queue declarations.
- */
-#define TAILQ_HEAD(name, type) \
-struct name { \
- struct type *tqh_first; /* first element */ \
- struct type **tqh_last; /* addr of last next element */ \
- TRACEBUF \
-}
-
-#define TAILQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).tqh_first }
-
-#define TAILQ_ENTRY(type) \
-struct { \
- struct type *tqe_next; /* next element */ \
- struct type **tqe_prev; /* address of previous next element */ \
- TRACEBUF \
-}
-
-/*
- * Tail queue functions.
- */
-#if (defined(_KERNEL) && defined(INVARIANTS))
-#define QMD_TAILQ_CHECK_HEAD(head, field) do { \
- if (!TAILQ_EMPTY(head) && \
- TAILQ_FIRST((head))->field.tqe_prev != \
- &TAILQ_FIRST((head))) \
- panic("Bad tailq head %p first->prev != head", (head)); \
-} while (0)
-
-#define QMD_TAILQ_CHECK_TAIL(head, field) do { \
- if (*(head)->tqh_last != NULL) \
- panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
-} while (0)
-
-#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
- if (TAILQ_NEXT((elm), field) != NULL && \
- TAILQ_NEXT((elm), field)->field.tqe_prev != \
- &((elm)->field.tqe_next)) \
- panic("Bad link elm %p next->prev != elm", (elm)); \
-} while (0)
-
-#define QMD_TAILQ_CHECK_PREV(elm, field) do { \
- if (*(elm)->field.tqe_prev != (elm)) \
- panic("Bad link elm %p prev->next != elm", (elm)); \
-} while (0)
-#else
-#define QMD_TAILQ_CHECK_HEAD(head, field)
-#define QMD_TAILQ_CHECK_TAIL(head, headname)
-#define QMD_TAILQ_CHECK_NEXT(elm, field)
-#define QMD_TAILQ_CHECK_PREV(elm, field)
-#endif /* (_KERNEL && INVARIANTS) */
-
-#define TAILQ_CONCAT(head1, head2, field) do { \
- if (!TAILQ_EMPTY(head2)) { \
- *(head1)->tqh_last = (head2)->tqh_first; \
- (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
- (head1)->tqh_last = (head2)->tqh_last; \
- TAILQ_INIT((head2)); \
- QMD_TRACE_HEAD(head1); \
- QMD_TRACE_HEAD(head2); \
- } \
-} while (0)
-
-#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
-
-#define TAILQ_FIRST(head) ((head)->tqh_first)
-
-#define TAILQ_FOREACH(var, head, field) \
- for ((var) = TAILQ_FIRST((head)); \
- (var); \
- (var) = TAILQ_NEXT((var), field))
-
-#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = TAILQ_FIRST((head)); \
- (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
- for ((var) = TAILQ_LAST((head), headname); \
- (var); \
- (var) = TAILQ_PREV((var), headname, field))
-
-#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
- for ((var) = TAILQ_LAST((head), headname); \
- (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
- (var) = (tvar))
-
-#define TAILQ_INIT(head) do { \
- TAILQ_FIRST((head)) = NULL; \
- (head)->tqh_last = &TAILQ_FIRST((head)); \
- QMD_TRACE_HEAD(head); \
-} while (0)
-
-#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
- QMD_TAILQ_CHECK_NEXT(listelm, field); \
- if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
- TAILQ_NEXT((elm), field)->field.tqe_prev = \
- &TAILQ_NEXT((elm), field); \
- else { \
- (head)->tqh_last = &TAILQ_NEXT((elm), field); \
- QMD_TRACE_HEAD(head); \
- } \
- TAILQ_NEXT((listelm), field) = (elm); \
- (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
- QMD_TRACE_ELEM(&(elm)->field); \
- QMD_TRACE_ELEM(&listelm->field); \
-} while (0)
-
-#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
- QMD_TAILQ_CHECK_PREV(listelm, field); \
- (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
- TAILQ_NEXT((elm), field) = (listelm); \
- *(listelm)->field.tqe_prev = (elm); \
- (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
- QMD_TRACE_ELEM(&(elm)->field); \
- QMD_TRACE_ELEM(&listelm->field); \
-} while (0)
-
-#define TAILQ_INSERT_HEAD(head, elm, field) do { \
- QMD_TAILQ_CHECK_HEAD(head, field); \
- if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
- TAILQ_FIRST((head))->field.tqe_prev = \
- &TAILQ_NEXT((elm), field); \
- else \
- (head)->tqh_last = &TAILQ_NEXT((elm), field); \
- TAILQ_FIRST((head)) = (elm); \
- (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
- QMD_TRACE_HEAD(head); \
- QMD_TRACE_ELEM(&(elm)->field); \
-} while (0)
-
-#define TAILQ_INSERT_TAIL(head, elm, field) do { \
- QMD_TAILQ_CHECK_TAIL(head, field); \
- TAILQ_NEXT((elm), field) = NULL; \
- (elm)->field.tqe_prev = (head)->tqh_last; \
- *(head)->tqh_last = (elm); \
- (head)->tqh_last = &TAILQ_NEXT((elm), field); \
- QMD_TRACE_HEAD(head); \
- QMD_TRACE_ELEM(&(elm)->field); \
-} while (0)
-
-#define TAILQ_LAST(head, headname) \
- (*(((struct headname *)((head)->tqh_last))->tqh_last))
-
-#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-
-#define TAILQ_PREV(elm, headname, field) \
- (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
-
-#define TAILQ_REMOVE(head, elm, field) do { \
- QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
- QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
- QMD_TAILQ_CHECK_NEXT(elm, field); \
- QMD_TAILQ_CHECK_PREV(elm, field); \
- if ((TAILQ_NEXT((elm), field)) != NULL) \
- TAILQ_NEXT((elm), field)->field.tqe_prev = \
- (elm)->field.tqe_prev; \
- else { \
- (head)->tqh_last = (elm)->field.tqe_prev; \
- QMD_TRACE_HEAD(head); \
- } \
- *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
- TRASHIT(*oldnext); \
- TRASHIT(*oldprev); \
- QMD_TRACE_ELEM(&(elm)->field); \
-} while (0)
-
-#define TAILQ_SWAP(head1, head2, type, field) do { \
- struct type *swap_first = (head1)->tqh_first; \
- struct type **swap_last = (head1)->tqh_last; \
- (head1)->tqh_first = (head2)->tqh_first; \
- (head1)->tqh_last = (head2)->tqh_last; \
- (head2)->tqh_first = swap_first; \
- (head2)->tqh_last = swap_last; \
- if ((swap_first = (head1)->tqh_first) != NULL) \
- swap_first->field.tqe_prev = &(head1)->tqh_first; \
- else \
- (head1)->tqh_last = &(head1)->tqh_first; \
- if ((swap_first = (head2)->tqh_first) != NULL) \
- swap_first->field.tqe_prev = &(head2)->tqh_first; \
- else \
- (head2)->tqh_last = &(head2)->tqh_first; \
-} while (0)
-
-#endif /* !_SYS_QUEUE_H_ */
+++ /dev/null
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- *
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- * Copyright (c) 2005, Keir A Fraser
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _MM_H_
-#define _MM_H_
-
-#if defined(__i386__)
-#include <xen/arch-x86_32.h>
-#elif defined(__x86_64__)
-#include <xen/arch-x86_64.h>
-#elif defined(__arm__) || defined(__aarch64__)
-#include <xen/arch-arm.h>
-#else
-#error "Unsupported architecture"
-#endif
-#include <xen/xen.h>
-
-#include <mini-os/arch_limits.h>
-#include <mini-os/arch_mm.h>
-
-#define STACK_SIZE_PAGE_ORDER __STACK_SIZE_PAGE_ORDER
-#define STACK_SIZE __STACK_SIZE
-
-
-void init_mm(void);
-unsigned long alloc_pages(int order);
-#define alloc_page() alloc_pages(0)
-void free_pages(void *pointer, int order);
-#define free_page(p) free_pages(p, 0)
-
-static __inline__ int get_order(unsigned long size)
-{
- int order;
- size = (size-1) >> PAGE_SHIFT;
- for ( order = 0; size; order++ )
- size >>= 1;
- return order;
-}
-
-void arch_init_demand_mapping_area(unsigned long max_pfn);
-void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p);
-void arch_init_p2m(unsigned long max_pfn_p);
-
-unsigned long allocate_ondemand(unsigned long n, unsigned long alignment);
-/* map f[i*stride]+i*increment for i in 0..n-1, aligned on alignment pages */
-void *map_frames_ex(const unsigned long *f, unsigned long n, unsigned long stride,
- unsigned long increment, unsigned long alignment, domid_t id,
- int *err, unsigned long prot);
-void do_map_frames(unsigned long addr,
- const unsigned long *f, unsigned long n, unsigned long stride,
- unsigned long increment, domid_t id, int *err, unsigned long prot);
-int unmap_frames(unsigned long va, unsigned long num_frames);
-unsigned long alloc_contig_pages(int order, unsigned int addr_bits);
-#ifdef HAVE_LIBC
-extern unsigned long heap, brk, heap_mapped, heap_end;
-#endif
-
-int free_physical_pages(xen_pfn_t *mfns, int n);
-void fini_mm(void);
-
-#endif /* _MM_H_ */
+++ /dev/null
-#include <mini-os/wait.h>
-#ifdef HAVE_LWIP
-#include <lwip/netif.h>
-#endif
-struct netfront_dev;
-struct netfront_dev *init_netfront(char *nodename, void (*netif_rx)(unsigned char *data, int len), unsigned char rawmac[6], char **ip);
-void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len);
-void shutdown_netfront(struct netfront_dev *dev);
-#ifdef HAVE_LIBC
-int netfront_tap_open(char *nodename);
-ssize_t netfront_receive(struct netfront_dev *dev, unsigned char *data, size_t len);
-#endif
-
-extern struct wait_queue_head netfront_queue;
-
-#ifdef HAVE_LWIP
-/* Call this to bring up the netfront interface and the lwIP stack.
- * N.B. _must_ be called from a thread; it's not safe to call this from
- * app_main(). */
-void start_networking(void);
-void stop_networking(void);
-
-void networking_set_addr(struct ip_addr *ipaddr, struct ip_addr *netmask, struct ip_addr *gw);
-#endif
+++ /dev/null
-#include <mini-os/types.h>
-#include <xen/io/pciif.h>
-struct pcifront_dev;
-void pcifront_watches(void *opaque);
-struct pcifront_dev *init_pcifront(char *nodename);
-void pcifront_op(struct pcifront_dev *dev, struct xen_pci_op *op);
-void pcifront_scan(struct pcifront_dev *dev, void (*fun)(unsigned int domain, unsigned int bus, unsigned slot, unsigned int fun));
-int pcifront_conf_read(struct pcifront_dev *dev,
- unsigned int dom,
- unsigned int bus, unsigned int slot, unsigned int fun,
- unsigned int off, unsigned int size, unsigned int *val);
-int pcifront_conf_write(struct pcifront_dev *dev,
- unsigned int dom,
- unsigned int bus, unsigned int slot, unsigned int fun,
- unsigned int off, unsigned int size, unsigned int val);
-int pcifront_enable_msi(struct pcifront_dev *dev,
- unsigned int dom,
- unsigned int bus, unsigned int slot, unsigned int fun);
-int pcifront_disable_msi(struct pcifront_dev *dev,
- unsigned int dom,
- unsigned int bus, unsigned int slot, unsigned int fun);
-int pcifront_enable_msix(struct pcifront_dev *dev,
- unsigned int dom,
- unsigned int bus, unsigned int slot, unsigned int fun,
- struct xen_msix_entry *entries, int n);
-int pcifront_disable_msix(struct pcifront_dev *dev,
- unsigned int dom,
- unsigned int bus, unsigned int slot, unsigned int fun);
-void shutdown_pcifront(struct pcifront_dev *dev);
+++ /dev/null
-#ifndef _POSIX_ARPA_INET_H_
-#define _POSIX_ARPA_INET_H_
-
-#include <lwip/inet.h>
-
-#endif /* _POSIX_ARPA_INET_H_ */
-
+++ /dev/null
-#ifndef _POSIX_DIRENT_H
-#define _POSIX_DIRENT_H
-
-#include <stdint.h>
-
-struct dirent {
- char *d_name;
-};
-
-typedef struct {
- struct dirent dirent;
- char *name;
- int32_t offset;
- char **entries;
- int32_t curentry;
- int32_t nbentries;
- int has_more;
-} DIR;
-
-DIR *opendir(const char *name);
-struct dirent *readdir(DIR *dir);
-int closedir(DIR *dir);
-
-#endif /* _POSIX_DIRENT_H */
+++ /dev/null
-#ifndef _POSIX_ERR_H
-#define _POSIX_ERR_H
-
-#include <stdarg.h>
-
-void err(int eval, const char *fmt, ...);
-void errx(int eval, const char *fmt, ...);
-void warn(const char *fmt, ...);
-void warnx(const char *fmt, ...);
-void verr(int eval, const char *fmt, va_list args);
-void verrx(int eval, const char *fmt, va_list args);
-void vwarn(const char *fmt, va_list args);
-void vwarnx(const char *fmt, va_list args);
-
-#endif /* _POSIX_ERR_H */
+++ /dev/null
-#ifndef _POSIX_FCNTL_H
-#define _POSIX_FCNTL_H
-
-#include_next <fcntl.h>
-
-#define F_ULOCK 0
-#define F_LOCK 1
-#define F_TLOCK 2
-#define F_TEST 3
-
-#endif /* _POSIX_FCNTL_H */
+++ /dev/null
-#ifndef _POSIX_LIMITS_H
-#define _POSIX_LIMITS_H
-
-#include <mini-os/arch_limits.h>
-
-#define CHAR_BIT 8
-
-#define SCHAR_MAX 0x7f
-#define SCHAR_MIN (-SCHAR_MAX-1)
-#define UCHAR_MAX 0xff
-
-#ifdef __CHAR_UNSIGNED__
-# define CHAR_MIN 0
-# define CHAR_MAX UCHAR_MAX
-#else
-# define CHAR_MIN SCHAR_MIN
-# define CHAR_MAX SCHAR_MAX
-#endif
-
-#define INT_MAX 0x7fffffff
-#define INT_MIN (-INT_MAX-1)
-#define UINT_MAX 0xffffffff
-
-#define SHRT_MIN (-0x8000)
-#define SHRT_MAX 0x7fff
-#define USHRT_MAX 0xffff
-
-#if defined(__x86_64__)
-# define LONG_MAX 0x7fffffffffffffffL
-# define ULONG_MAX 0xffffffffffffffffUL
-#else
-# define LONG_MAX 0x7fffffffL
-# define ULONG_MAX 0xffffffffUL
-#endif
-#define LONG_MIN (-LONG_MAX-1L)
-
-#define LLONG_MAX 0x7fffffffffffffffLL
-#define LLONG_MIN (-LLONG_MAX-1LL)
-#define ULLONG_MAX 0xffffffffffffffffULL
-
-#define LONG_LONG_MIN LLONG_MIN
-#define LONG_LONG_MAX LLONG_MAX
-#define ULONG_LONG_MAX ULLONG_MAX
-
-#define PATH_MAX __PAGE_SIZE
-#define PAGE_SIZE __PAGE_SIZE
-
-#endif /* _POSIX_LIMITS_H */
+++ /dev/null
-/*
- * This code is mostly taken from NetBSD net/if.h
- * Changes: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
- *
- ******************************************************************************
- *
- * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by William Studenmund and Jason R. Thorpe.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Copyright (c) 1982, 1986, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#ifndef _NET_IF_H_
-#define _NET_IF_H_
-
-/*
- * Length of interface external name, including terminating '\0'.
- * Note: this is the same size as a generic device's external name.
- */
-#define IF_NAMESIZE 16
-
-struct if_nameindex {
- unsigned int if_index; /* 1, 2, ... */
- char *if_name; /* null terminated name: "le0", ... */
-};
-
-unsigned int if_nametoindex(const char *);
-char * if_indextoname(unsigned int, char *);
-struct if_nameindex * if_nameindex(void);
-void if_freenameindex(struct if_nameindex *);
-
-#endif /* !_NET_IF_H_ */
-
+++ /dev/null
-#ifndef _POSIX_NETDB_H_
-#define _POSIX_NETDB_H_
-
-struct hostent {
- char *h_addr;
-};
-#define gethostbyname(buf) NULL
-
-#endif /* _POSIX_NETDB_H_ */
+++ /dev/null
-#ifndef _POSIX_SYS_IN_H_
-#define _POSIX_SYS_IN_H_
-
-#include <fcntl.h>
-#include <lwip/sockets.h>
-
-#endif /* _POSIX_SYS_IN_H_ */
+++ /dev/null
-#ifndef _POSIX_SYS_TCP_H_
-#define _POSIX_SYS_TCP_H_
-
-#include <lwip/tcp.h>
-
-#endif /* _POSIX_SYS_TCP_H_ */
+++ /dev/null
-#include <sys/poll.h>
+++ /dev/null
-#ifndef _POSIX_PTHREAD_H
-#define _POSIX_PTHREAD_H
-
-#include <stdlib.h>
-
-/* Let's be single-threaded for now. */
-
-typedef struct {
- void *ptr;
-} *pthread_key_t;
-static inline int pthread_key_create(pthread_key_t *key, void (*destr_function)(void*))
-{
- *key = malloc(sizeof(**key));
- (*key)->ptr = NULL;
- return 0;
-}
-static inline int pthread_setspecific(pthread_key_t key, const void *pointer)
-{
- key->ptr = (void*) pointer;
- return 0;
-}
-static inline void *pthread_getspecific(pthread_key_t key)
-{
- return key->ptr;
-}
-static inline int pthread_key_delete(pthread_key_t key)
-{
- free(key);
- return 0;
-}
-
-
-
-typedef struct {} pthread_mutexattr_t;
-static inline int pthread_mutexattr_init(pthread_mutexattr_t *mattr) { return 0; }
-#define PTHREAD_MUTEX_NORMAL 0
-#define PTHREAD_MUTEX_RECURSIVE 1
-static inline int pthread_mutexattr_settype(pthread_mutexattr_t *mattr, int kind) { return 0; }
-static inline int pthread_mutexattr_destroy(pthread_mutexattr_t *mattr) { return 0; }
-typedef struct {} pthread_mutex_t;
-#define PTHREAD_MUTEX_INITIALIZER {}
-static inline int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *mattr) { return 0; }
-static inline int pthread_mutex_lock(pthread_mutex_t *mutex) { return 0; }
-static inline int pthread_mutex_unlock(pthread_mutex_t *mutex) { return 0; }
-
-
-
-typedef struct {
- int done;
-} pthread_once_t;
-#define PTHREAD_ONCE_INIT { 0 }
-
-static inline int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
-{
- if (!once_control->done) {
- once_control->done = 1;
- init_routine();
- }
- return 0;
-}
-
-#define __thread
-
-#endif /* _POSIX_PTHREAD_H */
+++ /dev/null
-#ifndef _POSIX_SIGNAL_H
-#define _POSIX_SIGNAL_H
-
-#include_next <signal.h>
-
-int sigaction(int signum, const struct sigaction * __restrict,
- struct sigaction * __restrict);
-
-#endif
-
+++ /dev/null
-#ifndef _POSIX_STDLIB_H
-#define _POSIX_STDLIB_H
-
-#include_next <stdlib.h>
-
-#define realpath(p,r) strcpy(r,p)
-
-#endif /* _POSIX_STDLIB_H */
+++ /dev/null
-#ifndef _POSIX_STRINGS_H
-#define _POSIX_STRINGS_H
-
-#include <string.h>
-
-#define bzero(ptr, size) (memset((ptr), '\0', (size)), (void) 0)
-
-int ffs (int i);
-int ffsl (long int li);
-int ffsll (long long int lli);
-
-#endif /* _POSIX_STRINGS_H */
+++ /dev/null
-#ifndef _POSIX_SYS_IOCTL_H
-#define _POSIX_SYS_IOCTL_H
-
-int ioctl(int fd, int request, ...);
-
-#define _IOC_NONE 0
-#define _IOC_WRITE 1
-#define _IOC_READ 2
-
-#define _IOC(rw, class, n, size) \
- (((rw ) << 30) | \
- ((class) << 22) | \
- ((n ) << 14) | \
- ((size ) << 0))
-
-#endif /* _POSIX_SYS_IOCTL_H */
+++ /dev/null
-#ifndef _POSIX_SYS_MMAN_H
-#define _POSIX_SYS_MMAN_H
-
-#define PROT_READ 0x1
-#define PROT_WRITE 0x2
-#define PROT_EXEC 0x4
-
-#define MAP_SHARED 0x01
-#define MAP_PRIVATE 0x02
-#define MAP_ANON 0x20
-
-/* Pages are always resident anyway */
-#define MAP_LOCKED 0x0
-
-#define MAP_FAILED ((void*)0)
-
-void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) asm("mmap64");
-int munmap(void *start, size_t length);
-static inline mlock(const void *addr, size_t len) { return 0; }
-static inline munlock(const void *addr, size_t len) { return 0; }
-
-#endif /* _POSIX_SYS_MMAN_H */
+++ /dev/null
-/*
- * This code is mostly taken from FreeBSD sys/sys/poll.h
- * Changes: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
- *
- ****************************************************************************
- * Copyright (c) 1997 Peter Wemm <peter@freebsd.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _POSIX_SYS_POLL_H_
-#define _POSIX_SYS_POLL_H_
-
-/*
- * This file is intended to be compatible with the traditional poll.h.
- */
-
-typedef unsigned int nfds_t;
-
-/*
- * This structure is passed as an array to poll(2).
- */
-struct pollfd {
- int fd; /* which file descriptor to poll */
- short events; /* events we are interested in */
- short revents; /* events found on return */
-};
-
-/*
- * Requestable events. If poll(2) finds any of these set, they are
- * copied to revents on return.
- * XXX Note that FreeBSD doesn't make much distinction between POLLPRI
- * and POLLRDBAND since none of the file types have distinct priority
- * bands - and only some have an urgent "mode".
- * XXX Note POLLIN isn't really supported in true SVSV terms. Under SYSV
- * POLLIN includes all of normal, band and urgent data. Most poll handlers
- * on FreeBSD only treat it as "normal" data.
- */
-#define POLLIN 0x0001 /* any readable data available */
-#define POLLPRI 0x0002 /* OOB/Urgent readable data */
-#define POLLOUT 0x0004 /* file descriptor is writeable */
-#define POLLRDNORM 0x0040 /* non-OOB/URG data available */
-#define POLLWRNORM POLLOUT /* no write type differentiation */
-#define POLLRDBAND 0x0080 /* OOB/Urgent readable data */
-#define POLLWRBAND 0x0100 /* OOB/Urgent data can be written */
-
-/*
- * These events are set if they occur regardless of whether they were
- * requested.
- */
-#define POLLERR 0x0008 /* some poll error occurred */
-#define POLLHUP 0x0010 /* file descriptor was "hung up" */
-#define POLLNVAL 0x0020 /* requested events "invalid" */
-
-int poll(struct pollfd _pfd[], nfds_t _nfds, int _timeout);
-
-#endif /* _POSIX_SYS_POLL_H_ */
+++ /dev/null
-#ifndef _POSIX_SELECT_H
-#define _POSIX_SELECT_H
-
-#include <sys/time.h>
-int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
-
-#endif /* _POSIX_SELECT_H */
+++ /dev/null
-#ifndef _POSIX_SYS_SOCKET_H_
-#define _POSIX_SYS_SOCKET_H_
-
-#include <fcntl.h>
-#include <lwip/sockets.h>
-
-int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
-int bind(int s, struct sockaddr *name, socklen_t namelen);
-int shutdown(int s, int how);
-int getpeername (int s, struct sockaddr *name, socklen_t *namelen);
-int getsockname (int s, struct sockaddr *name, socklen_t *namelen);
-int getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen);
-int setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen);
-int close(int s);
-int connect(int s, struct sockaddr *name, socklen_t namelen);
-int listen(int s, int backlog);
-int recv(int s, void *mem, int len, unsigned int flags);
-//int read(int s, void *mem, int len);
-int recvfrom(int s, void *mem, int len, unsigned int flags,
- struct sockaddr *from, socklen_t *fromlen);
-int send(int s, void *dataptr, int size, unsigned int flags);
-int sendto(int s, void *dataptr, int size, unsigned int flags,
- struct sockaddr *to, socklen_t tolen);
-int socket(int domain, int type, int protocol);
-//int write(int s, void *dataptr, int size);
-int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
- struct timeval *timeout);
-//int ioctl(int s, long cmd, void *argp);
-int getsockname(int s, struct sockaddr *name, socklen_t *namelen);
-
-#endif /* _POSIX_SYS_SOCKET_H_ */
+++ /dev/null
-#ifndef _POSIX_SYS_STAT_H
-#define _POSIX_SYS_STAT_H
-
-#include_next <sys/stat.h>
-int fstat(int fd, struct stat *buf) asm("fstat64");
-
-#endif /* _POSIX_SYS_STAT_H */
+++ /dev/null
-#ifndef _POSIX_SYSLOG_H
-#define _POSIX_SYSLOG_H
-
-#include <stdarg.h>
-
-#define LOG_PID 0
-#define LOG_CONS 0
-#define LOG_NDELAY 0
-#define LOG_ODELAY 0
-#define LOG_NOWAIT 0
-
-#define LOG_KERN 0
-#define LOG_USER 0
-#define LOG_MAIL 0
-#define LOG_NEWS 0
-#define LOG_UUCP 0
-#define LOG_DAEMON 0
-#define LOG_AUTH 0
-#define LOG_CRON 0
-#define LOG_LPR 0
-
-/* TODO: support */
-#define LOG_EMERG 0
-#define LOG_ALERT 1
-#define LOG_CRIT 2
-#define LOG_ERR 3
-#define LOG_WARNING 4
-#define LOG_NOTICE 5
-#define LOG_INFO 6
-#define LOG_DEBUG 7
-
-void openlog(const char *ident, int option, int facility);
-void syslog(int priority, const char *format, ...);
-void closelog(void);
-void vsyslog(int priority, const char *format, va_list ap);
-
-#endif /* _POSIX_SYSLOG_H */
+++ /dev/null
-#ifndef _POSIX_TERMIOS_H
-#define _POSIX_TERMIOS_H
-
-#define NCC 32
-
-struct termios {
- unsigned long c_iflag;
- unsigned long c_oflag;
- unsigned long c_lflag;
- unsigned long c_cflag;
- unsigned char c_cc[NCC];
-};
-
-/* modem lines */
-#define TIOCM_DTR 0x002
-#define TIOCM_RTS 0x004
-#define TIOCM_CTS 0x020
-#define TIOCM_CAR 0x040
-#define TIOCM_RI 0x080
-#define TIOCM_DSR 0x100
-
-/* c_iflag */
-#define IGNBRK 0x00000001
-#define BRKINT 0x00000002
-#define IGNPAR 0x00000004
-#define PARMRK 0x00000008
-#define INPCK 0x00000010
-#define ISTRIP 0x00000020
-#define INLCR 0x00000040
-#define IGNCR 0x00000080
-#define ICRNL 0x00000100
-#define IUCLC 0x00000200
-#define IXON 0x00000400
-#define IXANY 0x00000800
-#define IXOFF 0x00001000
-#define IMAXBEL 0x00002000
-#define IUTF8 0x00004000
-
-/* c_oflag */
-#define OPOST 0x00000001
-#define OLCUC 0x00000002
-#define ONLCR 0x00000004
-#define OCRNL 0x00000008
-#define ONOCR 0x00000010
-#define ONLRET 0x00000020
-#define OFILL 0x00000040
-#define OFDEL 0x00000080
-
-/* c_lflag */
-#define ISIG 0x00000001
-#define ICANON 0x00000002
-#define XCASE 0x00000004
-#define ECHO 0x00000008
-#define ECHOE 0x00000010
-#define ECHOK 0x00000020
-#define ECHONL 0x00000040
-#define NOFLSH 0x00000080
-#define TOSTOP 0x00000100
-#define ECHOCTL 0x00000200
-#define ECHOPRT 0x00000400
-#define ECHOKE 0x00000800
-#define FLUSHO 0x00002000
-#define PENDIN 0x00004000
-#define IEXTEN 0x00008000
-
-/* c_cflag */
-#define CSIZE 0x00000030
-#define CS8 0x00000030
-#define CSTOPB 0x00000040
-#define CREAD 0x00000080
-#define PARENB 0x00000100
-#define PARODD 0x00000200
-#define HUPCL 0x00000400
-#define CLOCAL 0x00000800
-
-/* c_cc */
-#define VTIME 5
-#define VMIN 6
-
-#define TCSANOW 0
-#define TCSADRAIN 1
-#define TCSAFLUSH 2
-
-int tcsetattr(int fildes, int action, const struct termios *tios);
-int tcgetattr(int fildes, struct termios *tios);
-
-#endif /* _POSIX_TERMIOS_H */
+++ /dev/null
-#ifndef _POSIX_TIME_H
-#define _POSIX_TIME_H
-
-#include <sys/time.h>
-#define CLOCK_MONOTONIC 2
-#include_next <time.h>
-
-int nanosleep(const struct timespec *req, struct timespec *rem);
-int clock_gettime(clockid_t clock_id, struct timespec *tp);
-
-#endif /* _POSIX_TIME_H */
+++ /dev/null
-#ifndef _POSIX_UNISTD_H
-#define _POSIX_UNISTD_H
-
-#include_next <unistd.h>
-
-uid_t getuid(void);
-uid_t geteuid(void);
-gid_t getgid(void);
-gid_t getegid(void);
-int gethostname(char *name, size_t namelen);
-size_t getpagesize(void);
-int ftruncate(int fd, off_t length);
-int lockf(int fd, int cmd, off_t len);
-int nice(int inc);
-
-#endif /* _POSIX_UNISTD_H */
+++ /dev/null
-#ifndef __SCHED_H__
-#define __SCHED_H__
-
-#include <mini-os/list.h>
-#include <mini-os/time.h>
-#include <mini-os/arch_sched.h>
-#ifdef HAVE_LIBC
-#include <sys/reent.h>
-#endif
-
-struct thread
-{
- char *name;
- char *stack;
- /* keep in that order */
- unsigned long sp; /* Stack pointer */
- unsigned long ip; /* Instruction pointer */
- MINIOS_TAILQ_ENTRY(struct thread) thread_list;
- uint32_t flags;
- s_time_t wakeup_time;
-#ifdef HAVE_LIBC
- struct _reent reent;
-#endif
-};
-
-extern struct thread *idle_thread;
-void idle_thread_fn(void *unused);
-
-#define RUNNABLE_FLAG 0x00000001
-
-#define is_runnable(_thread) (_thread->flags & RUNNABLE_FLAG)
-#define set_runnable(_thread) (_thread->flags |= RUNNABLE_FLAG)
-#define clear_runnable(_thread) (_thread->flags &= ~RUNNABLE_FLAG)
-
-#define switch_threads(prev, next) arch_switch_threads(prev, next)
-
- /* Architecture specific setup of thread creation. */
-struct thread* arch_create_thread(char *name, void (*function)(void *),
- void *data);
-
-void init_sched(void);
-void run_idle_thread(void);
-struct thread* create_thread(char *name, void (*function)(void *), void *data);
-void exit_thread(void) __attribute__((noreturn));
-void schedule(void);
-
-#ifdef __INSIDE_MINIOS__
-#define current get_current()
-#endif
-
-void wake(struct thread *thread);
-void block(struct thread *thread);
-void msleep(uint32_t millisecs);
-
-#endif /* __SCHED_H__ */
+++ /dev/null
-#ifndef _SEMAPHORE_H_
-#define _SEMAPHORE_H_
-
-#include <mini-os/wait.h>
-#include <mini-os/spinlock.h>
-
-/*
- * Implementation of semaphore in Mini-os is simple, because
- * there are no preemptive threads, the atomicity is guaranteed.
- */
-
-struct semaphore
-{
- int count;
- struct wait_queue_head wait;
-};
-
-/*
- * the semaphore definition
- */
-struct rw_semaphore {
- signed long count;
- spinlock_t wait_lock;
- int debug;
-};
-
-#define __SEMAPHORE_INITIALIZER(name, n) \
-{ \
- .count = n, \
- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-}
-
-#define __MUTEX_INITIALIZER(name) \
- __SEMAPHORE_INITIALIZER(name,1)
-
-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
-
-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
-
-static inline void init_SEMAPHORE(struct semaphore *sem, int count)
-{
- sem->count = count;
- init_waitqueue_head(&sem->wait);
-}
-
-#define init_MUTEX(sem) init_SEMAPHORE(sem, 1)
-
-static inline int trydown(struct semaphore *sem)
-{
- unsigned long flags;
- int ret = 0;
- local_irq_save(flags);
- if (sem->count > 0) {
- ret = 1;
- sem->count--;
- }
- local_irq_restore(flags);
- return ret;
-}
-
-static void inline down(struct semaphore *sem)
-{
- unsigned long flags;
- while (1) {
- wait_event(sem->wait, sem->count > 0);
- local_irq_save(flags);
- if (sem->count > 0)
- break;
- local_irq_restore(flags);
- }
- sem->count--;
- local_irq_restore(flags);
-}
-
-static void inline up(struct semaphore *sem)
-{
- unsigned long flags;
- local_irq_save(flags);
- sem->count++;
- wake_up(&sem->wait);
- local_irq_restore(flags);
-}
-
-/* FIXME! Thre read/write semaphores are unimplemented! */
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
- sem->count = 1;
-}
-
-static inline void down_read(struct rw_semaphore *sem)
-{
-}
-
-
-static inline void up_read(struct rw_semaphore *sem)
-{
-}
-
-static inline void up_write(struct rw_semaphore *sem)
-{
-}
-
-static inline void down_write(struct rw_semaphore *sem)
-{
-}
-
-#endif /* _SEMAPHORE_H */
+++ /dev/null
-#ifndef __ASM_SPINLOCK_H
-#define __ASM_SPINLOCK_H
-
-#include <mini-os/lib.h>
-
-/*
- * Your basic SMP spinlocks, allowing only a single CPU anywhere
- */
-
-typedef struct {
- volatile unsigned int slock;
-} spinlock_t;
-
-
-#include <mini-os/arch_spinlock.h>
-
-
-#define SPINLOCK_MAGIC 0xdead4ead
-
-#define SPIN_LOCK_UNLOCKED ARCH_SPIN_LOCK_UNLOCKED
-
-#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-
-/*
- * Simple spin lock operations. There are two variants, one clears IRQ's
- * on the local processor, one does not.
- *
- * We make no fairness assumptions. They have a cost.
- */
-
-#define spin_is_locked(x) arch_spin_is_locked(x)
-
-#define spin_unlock_wait(x) arch_spin_unlock_wait(x)
-
-
-#define _spin_trylock(lock) ({_raw_spin_trylock(lock) ? \
- 1 : ({ 0;});})
-
-#define _spin_lock(lock) \
-do { \
- _raw_spin_lock(lock); \
-} while(0)
-
-#define _spin_unlock(lock) \
-do { \
- _raw_spin_unlock(lock); \
-} while (0)
-
-
-#define spin_lock(lock) _spin_lock(lock)
-#define spin_unlock(lock) _spin_unlock(lock)
-
-#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
-
-#endif
+++ /dev/null
-#ifndef _MINIOS_SYS_LOCK_H_
-#define _MINIOS_SYS_LOCK_H_
-
-#ifdef HAVE_LIBC
-
-/* Due to inclusion loop, we can not include sched.h, so have to hide things */
-
-#include <mini-os/waittypes.h>
-
-
-typedef struct {
- int busy;
- struct wait_queue_head wait;
-} _LOCK_T;
-
-#define __LOCK_INIT(class,lock) \
- class _LOCK_T lock = { .wait = __WAIT_QUEUE_HEAD_INITIALIZER(lock.wait) }
-int ___lock_init(_LOCK_T *lock);
-int ___lock_acquire(_LOCK_T *lock);
-int ___lock_try_acquire(_LOCK_T *lock);
-int ___lock_release(_LOCK_T *lock);
-int ___lock_close(_LOCK_T *lock);
-#define __lock_init(__lock) ___lock_init(&__lock)
-#define __lock_acquire(__lock) ___lock_acquire(&__lock)
-#define __lock_release(__lock) ___lock_release(&__lock)
-#define __lock_try_acquire(__lock) ___lock_try_acquire(&__lock)
-#define __lock_close(__lock) 0
-
-
-typedef struct {
- struct thread *owner;
- int count;
- struct wait_queue_head wait;
-} _LOCK_RECURSIVE_T;
-
-#define __LOCK_INIT_RECURSIVE(class, lock) \
- class _LOCK_RECURSIVE_T lock = { .wait = __WAIT_QUEUE_HEAD_INITIALIZER((lock).wait) }
-
-int ___lock_init_recursive(_LOCK_RECURSIVE_T *lock);
-int ___lock_acquire_recursive(_LOCK_RECURSIVE_T *lock);
-int ___lock_try_acquire_recursive(_LOCK_RECURSIVE_T *lock);
-int ___lock_release_recursive(_LOCK_RECURSIVE_T *lock);
-int ___lock_close_recursive(_LOCK_RECURSIVE_T *lock);
-#define __lock_init_recursive(__lock) ___lock_init_recursive(&__lock)
-#define __lock_acquire_recursive(__lock) ___lock_acquire_recursive(&__lock)
-#define __lock_release_recursive(__lock) ___lock_release_recursive(&__lock)
-#define __lock_try_acquire_recursive(__lock) ___lock_try_acquire_recursive(&__lock)
-#define __lock_close_recursive(__lock) 0
-
-#endif
-
-#endif /* _MINIOS_SYS_LOCK_H_ */
+++ /dev/null
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
- ****************************************************************************
- *
- * File: time.h
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes: Grzegorz Milos (gm281@cam.ac.uk)
- * Robert Kaiser (kaiser@informatik.fh-wiesbaden.de)
- *
- * Date: Jul 2003, changes: Jun 2005, Sep 2006
- *
- * Environment: Xen Minimal OS
- * Description: Time and timer functions
- *
- ****************************************************************************
- */
-
-#ifndef _MINIOS_SYS_TIME_H_
-#define _MINIOS_SYS_TIME_H_
-
-#ifdef HAVE_LIBC
-#include_next <sys/time.h>
-
-#else
-struct timespec {
- time_t tv_sec;
- long tv_nsec;
-};
-
-struct timezone {
-};
-
-struct timeval {
- time_t tv_sec; /* seconds */
- suseconds_t tv_usec; /* microseconds */
-};
-
-int gettimeofday(struct timeval *tv, void *tz);
-
-#endif
-#ifdef HAVE_LIBC
-#include <sys/select.h>
-#endif
-
-#endif /* _MINIOS_SYS_TIME_H_ */
+++ /dev/null
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
- ****************************************************************************
- *
- * File: time.h
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes: Grzegorz Milos (gm281@cam.ac.uk)
- * Robert Kaiser (kaiser@informatik.fh-wiesbaden.de)
- *
- * Date: Jul 2003, changes: Jun 2005, Sep 2006
- *
- * Environment: Xen Minimal OS
- * Description: Time and timer functions
- *
- ****************************************************************************
- */
-
-#ifndef _MINIOS_TIME_H_
-#define _MINIOS_TIME_H_
-#include <mini-os/types.h>
-
-/*
- * System Time
- * 64 bit value containing the nanoseconds elapsed since boot time.
- * This value is adjusted by frequency drift.
- * NOW() returns the current time.
- * The other macros are for convenience to approximate short intervals
- * of real time into system time
- */
-typedef int64_t s_time_t;
-#define NOW() ((s_time_t)monotonic_clock())
-#define SECONDS(_s) (((s_time_t)(_s)) * 1000000000UL )
-#define TENTHS(_ts) (((s_time_t)(_ts)) * 100000000UL )
-#define HUNDREDTHS(_hs) (((s_time_t)(_hs)) * 10000000UL )
-#define MILLISECS(_ms) (((s_time_t)(_ms)) * 1000000UL )
-#define MICROSECS(_us) (((s_time_t)(_us)) * 1000UL )
-#define Time_Max ((s_time_t) 0x7fffffffffffffffLL)
-#define FOREVER Time_Max
-#define NSEC_TO_USEC(_nsec) ((_nsec) / 1000UL)
-#define NSEC_TO_MSEC(_nsec) ((_nsec) / 1000000ULL)
-#define NSEC_TO_SEC(_nsec) ((_nsec) / 1000000000ULL)
-
-/* wall clock time */
-typedef long time_t;
-typedef long suseconds_t;
-
-#include <sys/time.h>
-
-#ifdef HAVE_LIBC
-#include_next <time.h>
-#endif
-
-/* prototypes */
-void init_time(void);
-void fini_time(void);
-s_time_t get_s_time(void);
-s_time_t get_v_time(void);
-uint64_t monotonic_clock(void);
-void block_domain(s_time_t until);
-
-#endif /* _MINIOS_TIME_H_ */
+++ /dev/null
-/*
- * Copyright (c) 2010-2012 United States Government, as represented by
- * the Secretary of Defense. All rights reserved.
- *
- * This code has been derived from drivers/char/tpm.c
- * from the linux kernel
- *
- * Copyright (C) 2004 IBM Corporation
- *
- * This code has also been derived from drivers/char/tpm/tpm_tis.c
- * from the linux kernel
- *
- * Copyright (C) 2005, 2006 IBM Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, version 2
- * of the License
- */
-#ifndef TPM_TIS_H
-#define TPM_TIS_H
-
-#include <mini-os/types.h>
-#include <mini-os/byteorder.h>
-
-#define TPM_TIS_EN_LOCL0 1
-#define TPM_TIS_EN_LOCL1 (1 << 1)
-#define TPM_TIS_EN_LOCL2 (1 << 2)
-#define TPM_TIS_EN_LOCL3 (1 << 3)
-#define TPM_TIS_EN_LOCL4 (1 << 4)
-#define TPM_TIS_EN_LOCLALL (TPM_TIS_EN_LOCL0 | TPM_TIS_EN_LOCL1 | TPM_TIS_EN_LOCL2 | TPM_TIS_EN_LOCL3 | TPM_TIS_EN_LOCL4)
-#define TPM_TIS_LOCL_INT_TO_FLAG(x) (1 << x)
-#define TPM_BASEADDR 0xFED40000
-#define TPM_PROBE_IRQ 0xFFFF
-
-struct tpm_chip;
-
-struct tpm_chip* init_tpm_tis(unsigned long baseaddr, int localities, unsigned int irq);
-struct tpm_chip* init_tpm2_tis(unsigned long baseaddr, int localities, unsigned int irq);
-void shutdown_tpm_tis(struct tpm_chip* tpm);
-
-int tpm_tis_request_locality(struct tpm_chip* tpm, int locality);
-int tpm_tis_cmd(struct tpm_chip* tpm, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen);
-
-#ifdef HAVE_LIBC
-#include <sys/stat.h>
-#include <fcntl.h>
-/* POSIX IO functions:
- * use tpm_tis_open() to get a file descriptor to the tpm device
- * use write() on the fd to send a command to the backend. You must
- * include the entire command in a single call to write().
- * use read() on the fd to read the response. You can use
- * fstat() to get the size of the response and lseek() to seek on it.
- */
-int tpm_tis_open(struct tpm_chip* tpm);
-int tpm_tis_posix_read(int fd, uint8_t* buf, size_t count);
-int tpm_tis_posix_write(int fd, const uint8_t* buf, size_t count);
-int tpm_tis_posix_fstat(int fd, struct stat* buf);
-#endif
-
-#endif
+++ /dev/null
-/*
- * Copyright (c) 2010-2012 United States Government, as represented by
- * the Secretary of Defense. All rights reserved.
- *
- * This code has been derived from drivers/xen/tpmback/tpmback.c
- * from the xen 2.6.18 linux kernel
- *
- * Copyright (c) 2005, IBM Corporation
- *
- * which was itself derived from drivers/xen/netback/netback.c
- * from the xen 2.6.18 linux kernel
- *
- * Copyright (c) 2002-2004, K A Fraser
- *
- * This code has also been derived from drivers/xen/tpmback/xenbus.c
- * from the xen 2.6.18 linux kernel
- *
- * Copyright (C) 2005 IBM Corporation
- * Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
- *
- * This code has also been derived from drivers/xen/tpmback/interface.c
- * from the xen 2.6.18 linux kernel
- *
- * Copyright (c) 2005, IBM Corporation
- *
- * which was itself also derived from drvivers/xen/netback/interface.c
- * from the xen 2.6.18 linux kernel
- *
- * Copyright (c) 2004, Keir Fraser
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, version 2
- * of the License
- */
-
-#include <xen/io/tpmif.h>
-#include <xen/io/xenbus.h>
-#include <mini-os/types.h>
-#include <xen/xen.h>
-#ifndef TPMBACK_H
-#define TPMBACK_H
-
-struct tpmcmd {
- domid_t domid; /* Domid of the frontend */
- uint8_t locality; /* Locality requested by the frontend */
- unsigned int handle; /* Handle of the frontend */
- void *opaque; /* Opaque pointer taken from the tpmback instance */
-
- uint8_t* req; /* tpm command bits, allocated by driver, DON'T FREE IT */
- unsigned int req_len; /* Size of the command in buf - set by tpmback driver */
- unsigned int resp_len; /* Size of the outgoing command,
- you set this before passing the cmd object to tpmback_resp */
- uint8_t* resp; /* Buffer for response - YOU MUST ALLOCATE IT, YOU MUST ALSO FREE IT */
-};
-typedef struct tpmcmd tpmcmd_t;
-
-/* Initialize the tpm backend driver */
-void init_tpmback(void (*open_cb)(domid_t, unsigned int), void (*close_cb)(domid_t, unsigned int));
-
-/* Shutdown tpm backend driver */
-void shutdown_tpmback(void);
-
-/* Blocks until a tpm command is sent from any front end.
- * Returns a pointer to the tpm command to handle.
- * Do not try to free this pointer or the req buffer
- * This function will return NULL if the tpm backend driver
- * is shutdown or any other error occurs */
-tpmcmd_t* tpmback_req_any(void);
-
-/* Blocks until a tpm command from the frontend at domid/handle
- * is sent.
- * Returns NULL if domid/handle is not connected, tpmback is
- * shutdown or shutting down, or if there is an error
- */
-tpmcmd_t* tpmback_req(domid_t domid, unsigned int handle);
-
-/* Send the response to the tpm command back to the frontend
- * This function will free the tpmcmd object, but you must free the resp
- * buffer yourself */
-void tpmback_resp(tpmcmd_t* tpmcmd);
-
-/* Waits for the first frontend to connect and then sets domid and handle appropriately.
- * If one or more frontends are already connected, this will set domid and handle to one
- * of them arbitrarily. The main use for this function is to wait until a single
- * frontend connection has occured.
- * returns 0 on success, non-zero on failure */
-int tpmback_wait_for_frontend_connect(domid_t *domid, unsigned int *handle);
-
-/* returns the number of frontends connected */
-int tpmback_num_frontends(void);
-
-/* Returns the uuid of the specified frontend, NULL on error.
- * The return value is internally allocated, so don't free it */
-unsigned char* tpmback_get_uuid(domid_t domid, unsigned int handle);
-
-/* Get and set the opaque pointer for a tpmback instance */
-void* tpmback_get_opaque(domid_t domid, unsigned int handle);
-/* Returns zero if successful, nonzero on failure (no such frontend) */
-int tpmback_set_opaque(domid_t domid, unsigned int handle, void* opaque);
-
-/* Get the XSM context of the given domain (using the tpmback event channel) */
-int tpmback_get_peercontext(domid_t domid, unsigned int handle, void* buffer, int buflen);
-#endif
+++ /dev/null
-/*
- * Copyright (c) 2010-2012 United States Government, as represented by
- * the Secretary of Defense. All rights reserved.
- *
- * This code has been derived from drivers/char/tpm_vtpm.c
- * from the xen 2.6.18 linux kernel
- *
- * Copyright (C) 2006 IBM Corporation
- *
- * This code has also been derived from drivers/char/tpm_xen.c
- * from the xen 2.6.18 linux kernel
- *
- * Copyright (c) 2005, IBM Corporation
- *
- * which was itself derived from drivers/xen/netfront/netfront.c
- * from the linux kernel
- *
- * Copyright (c) 2002-2004, K A Fraser
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- */
-#ifndef TPMFRONT_H
-#define TPMFRONT_H
-
-#include <mini-os/types.h>
-#include <mini-os/os.h>
-#include <mini-os/events.h>
-#include <mini-os/wait.h>
-#include <xen/xen.h>
-#include <xen/io/xenbus.h>
-#include <xen/io/tpmif.h>
-
-struct tpmfront_dev {
- grant_ref_t ring_ref;
- evtchn_port_t evtchn;
-
- tpmif_shared_page_t *page;
-
- domid_t bedomid;
- char* nodename;
- char* bepath;
-
- XenbusState state;
-
- uint8_t waiting;
- struct wait_queue_head waitq;
-
- uint8_t* respbuf;
- size_t resplen;
-
-#ifdef HAVE_LIBC
- int fd;
-#endif
-
-};
-
-
-/*Initialize frontend */
-struct tpmfront_dev* init_tpmfront(const char* nodename);
-/*Shutdown frontend */
-void shutdown_tpmfront(struct tpmfront_dev* dev);
-
-/* Send a tpm command to the backend and wait for the response
- *
- * @dev - frontend device
- * @req - request buffer
- * @reqlen - length of request buffer
- * @resp - *resp will be set to internal response buffer, don't free it! Value is undefined on error
- * @resplen - *resplen will be set to the length of the response. Value is undefined on error
- *
- * returns 0 on success, non zero on failure.
- * */
-int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen);
-
-/* Set the locality used for communicating with a vTPM */
-int tpmfront_set_locality(struct tpmfront_dev* dev, int locality);
-
-#ifdef HAVE_LIBC
-#include <sys/stat.h>
-/* POSIX IO functions:
- * use tpmfront_open() to get a file descriptor to the tpm device
- * use write() on the fd to send a command to the backend. You must
- * include the entire command in a single call to write().
- * use read() on the fd to read the response. You can use
- * fstat() to get the size of the response and lseek() to seek on it.
- */
-int tpmfront_open(struct tpmfront_dev* dev);
-int tpmfront_posix_read(int fd, uint8_t* buf, size_t count);
-int tpmfront_posix_write(int fd, const uint8_t* buf, size_t count);
-int tpmfront_posix_fstat(int fd, struct stat* buf);
-#endif
-
-
-#endif
+++ /dev/null
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
- *
- * File: types.h
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes:
- *
- * Date: May 2003
- *
- * Environment: Xen Minimal OS
- * Description: a random collection of type definitions
- *
- ****************************************************************************
- * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
- ****************************************************************************
- */
-
-#ifndef _TYPES_H_
-#define _TYPES_H_
-#include <stddef.h>
-
-/* FreeBSD compat types */
-#ifndef HAVE_LIBC
-typedef unsigned char u_char;
-typedef unsigned int u_int;
-typedef unsigned long u_long;
-#endif
-#if defined(__i386__) || defined(__arm__)
-typedef long long quad_t;
-typedef unsigned long long u_quad_t;
-#elif defined(__x86_64__)
-typedef long quad_t;
-typedef unsigned long u_quad_t;
-#endif /* __i386__ || __x86_64__ */
-
-#ifdef HAVE_LIBC
-#include <limits.h>
-#include <stdint.h>
-#else
-#if defined(__i386__) || defined(__arm__)
-typedef unsigned int uintptr_t;
-typedef int intptr_t;
-#elif defined(__x86_64__) || defined(__aarch64__)
-typedef unsigned long uintptr_t;
-typedef long intptr_t;
-#endif /* __i386__ || __x86_64__ */
-typedef unsigned char uint8_t;
-typedef signed char int8_t;
-typedef unsigned short uint16_t;
-typedef signed short int16_t;
-typedef unsigned int uint32_t;
-typedef signed int int32_t;
-#if defined(__i386__) || defined(__arm__)
-typedef signed long long int64_t;
-typedef unsigned long long uint64_t;
-#elif defined(__x86_64__) || defined(__aarch64__)
-typedef signed long int64_t;
-typedef unsigned long uint64_t;
-#endif
-typedef uint64_t uintmax_t;
-typedef int64_t intmax_t;
-typedef int64_t off_t;
-#endif
-
-typedef intptr_t ptrdiff_t;
-
-
-#ifndef HAVE_LIBC
-typedef long ssize_t;
-#endif
-
-#endif /* _TYPES_H_ */
+++ /dev/null
-#ifndef __WAIT_H__
-#define __WAIT_H__
-
-#include <mini-os/sched.h>
-#include <mini-os/os.h>
-#include <mini-os/waittypes.h>
-
-#define DEFINE_WAIT(name) \
-struct wait_queue name = { \
- .thread = get_current(), \
- .waiting = 0, \
-}
-
-
-static inline void init_waitqueue_head(struct wait_queue_head *h)
-{
- MINIOS_STAILQ_INIT(h);
-}
-
-static inline void init_waitqueue_entry(struct wait_queue *q, struct thread *thread)
-{
- q->thread = thread;
- q->waiting = 0;
-}
-
-static inline void add_wait_queue(struct wait_queue_head *h, struct wait_queue *q)
-{
- if (!q->waiting) {
- MINIOS_STAILQ_INSERT_HEAD(h, q, thread_list);
- q->waiting = 1;
- }
-}
-
-static inline void remove_wait_queue(struct wait_queue_head *h, struct wait_queue *q)
-{
- if (q->waiting) {
- MINIOS_STAILQ_REMOVE(h, q, struct wait_queue, thread_list);
- q->waiting = 0;
- }
-}
-
-static inline void wake_up(struct wait_queue_head *head)
-{
- unsigned long flags;
- struct wait_queue *curr, *tmp;
- local_irq_save(flags);
- MINIOS_STAILQ_FOREACH_SAFE(curr, head, thread_list, tmp)
- wake(curr->thread);
- local_irq_restore(flags);
-}
-
-#define add_waiter(w, wq) do { \
- unsigned long flags; \
- local_irq_save(flags); \
- add_wait_queue(&wq, &w); \
- block(get_current()); \
- local_irq_restore(flags); \
-} while (0)
-
-#define remove_waiter(w, wq) do { \
- unsigned long flags; \
- local_irq_save(flags); \
- remove_wait_queue(&wq, &w); \
- local_irq_restore(flags); \
-} while (0)
-
-#define wait_event_deadline(wq, condition, deadline) do { \
- unsigned long flags; \
- DEFINE_WAIT(__wait); \
- if(condition) \
- break; \
- for(;;) \
- { \
- /* protect the list */ \
- local_irq_save(flags); \
- add_wait_queue(&wq, &__wait); \
- get_current()->wakeup_time = deadline; \
- clear_runnable(get_current()); \
- local_irq_restore(flags); \
- if((condition) || (deadline && NOW() >= deadline)) \
- break; \
- schedule(); \
- } \
- local_irq_save(flags); \
- /* need to wake up */ \
- wake(get_current()); \
- remove_wait_queue(&wq, &__wait); \
- local_irq_restore(flags); \
-} while(0)
-
-#define wait_event(wq, condition) wait_event_deadline(wq, condition, 0)
-
-
-
-#endif /* __WAIT_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-#ifndef __WAITTYPE_H__
-#define __WAITTYPE_H__
-
-#include <mini-os/list.h>
-
-struct thread;
-struct wait_queue
-{
- int waiting;
- struct thread *thread;
- MINIOS_STAILQ_ENTRY(struct wait_queue) thread_list;
-};
-
-/* TODO - lock required? */
-MINIOS_STAILQ_HEAD(wait_queue_head, struct wait_queue);
-
-#define DECLARE_WAIT_QUEUE_HEAD(name) \
- struct wait_queue_head name = MINIOS_STAILQ_HEAD_INITIALIZER(name)
-
-#define __WAIT_QUEUE_HEAD_INITIALIZER(name) MINIOS_STAILQ_HEAD_INITIALIZER(name)
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-#ifndef ARCH_ENDIAN_H
-#error "Do not include arch_endian by itself, include endian.h"
-#else
-
-#define __BYTE_ORDER __LITTLE_ENDIAN
-
-#endif
+++ /dev/null
-
-#ifndef __ARCH_LIMITS_H__
-#define __ARCH_LIMITS_H__
-
-#define __PAGE_SHIFT 12
-
-#ifdef __ASSEMBLY__
-#define __PAGE_SIZE (1 << __PAGE_SHIFT)
-#else
-#ifdef __x86_64__
-#define __PAGE_SIZE (1UL << __PAGE_SHIFT)
-#else
-#define __PAGE_SIZE (1ULL << __PAGE_SHIFT)
-#endif
-#endif
-
-#define __STACK_SIZE_PAGE_ORDER 4
-#define __STACK_SIZE (__PAGE_SIZE * (1 << __STACK_SIZE_PAGE_ORDER))
-
-#endif /* __ARCH_LIMITS_H__ */
+++ /dev/null
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- *
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- * Copyright (c) 2005, Keir A Fraser
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _ARCH_MM_H_
-#define _ARCH_MM_H_
-
-#ifndef __ASSEMBLY__
-#include <xen/xen.h>
-#if defined(__i386__)
-#include <xen/arch-x86_32.h>
-#elif defined(__x86_64__)
-#include <xen/arch-x86_64.h>
-#else
-#error "Unsupported architecture"
-#endif
-#endif
-
-#define L1_FRAME 1
-#define L2_FRAME 2
-#define L3_FRAME 3
-
-#define L1_PAGETABLE_SHIFT 12
-
-#if defined(__i386__)
-
-#define L2_PAGETABLE_SHIFT 21
-#define L3_PAGETABLE_SHIFT 30
-
-#define L1_PAGETABLE_ENTRIES 512
-#define L2_PAGETABLE_ENTRIES 512
-#define L3_PAGETABLE_ENTRIES 4
-
-#define PADDR_BITS 44
-#define PADDR_MASK ((1ULL << PADDR_BITS)-1)
-
-#define L2_MASK ((1UL << L3_PAGETABLE_SHIFT) - 1)
-
-/*
- * If starting from virtual address greater than 0xc0000000,
- * this value will be 2 to account for final mid-level page
- * directory which is always mapped in at this location.
- */
-#define NOT_L1_FRAMES 3
-#define PRIpte "016llx"
-#ifndef __ASSEMBLY__
-typedef uint64_t pgentry_t;
-#endif
-
-#elif defined(__x86_64__)
-
-#define L2_PAGETABLE_SHIFT 21
-#define L3_PAGETABLE_SHIFT 30
-#define L4_PAGETABLE_SHIFT 39
-
-#define L1_PAGETABLE_ENTRIES 512
-#define L2_PAGETABLE_ENTRIES 512
-#define L3_PAGETABLE_ENTRIES 512
-#define L4_PAGETABLE_ENTRIES 512
-
-/* These are page-table limitations. Current CPUs support only 40-bit phys. */
-#define PADDR_BITS 52
-#define VADDR_BITS 48
-#define PADDR_MASK ((1UL << PADDR_BITS)-1)
-#define VADDR_MASK ((1UL << VADDR_BITS)-1)
-
-#define L2_MASK ((1UL << L3_PAGETABLE_SHIFT) - 1)
-#define L3_MASK ((1UL << L4_PAGETABLE_SHIFT) - 1)
-
-#define NOT_L1_FRAMES 3
-#define PRIpte "016lx"
-#ifndef __ASSEMBLY__
-typedef unsigned long pgentry_t;
-#endif
-
-#endif
-
-#define L1_MASK ((1UL << L2_PAGETABLE_SHIFT) - 1)
-
-/* Given a virtual address, get an entry offset into a page table. */
-#define l1_table_offset(_a) \
- (((_a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
-#define l2_table_offset(_a) \
- (((_a) >> L2_PAGETABLE_SHIFT) & (L2_PAGETABLE_ENTRIES - 1))
-#define l3_table_offset(_a) \
- (((_a) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1))
-#if defined(__x86_64__)
-#define l4_table_offset(_a) \
- (((_a) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1))
-#endif
-
-#define _PAGE_PRESENT 0x001ULL
-#define _PAGE_RW 0x002ULL
-#define _PAGE_USER 0x004ULL
-#define _PAGE_PWT 0x008ULL
-#define _PAGE_PCD 0x010ULL
-#define _PAGE_ACCESSED 0x020ULL
-#define _PAGE_DIRTY 0x040ULL
-#define _PAGE_PAT 0x080ULL
-#define _PAGE_PSE 0x080ULL
-#define _PAGE_GLOBAL 0x100ULL
-
-#if defined(__i386__)
-#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
-#define L1_PROT_RO (_PAGE_PRESENT|_PAGE_ACCESSED)
-#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY |_PAGE_USER)
-#define L3_PROT (_PAGE_PRESENT)
-#elif defined(__x86_64__)
-#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
-#define L1_PROT_RO (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_USER)
-#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
-#define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
-#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
-#endif /* __i386__ || __x86_64__ */
-
-/* flags for ioremap */
-#define IO_PROT (L1_PROT)
-#define IO_PROT_NOCACHE (L1_PROT | _PAGE_PCD)
-
-/* for P2M */
-#define INVALID_P2M_ENTRY (~0UL)
-
-#include "arch_limits.h"
-#define PAGE_SIZE __PAGE_SIZE
-#define PAGE_SHIFT __PAGE_SHIFT
-#define PAGE_MASK (~(PAGE_SIZE-1))
-
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT)
-#define PFN_DOWN(x) ((x) >> L1_PAGETABLE_SHIFT)
-#define PFN_PHYS(x) ((uint64_t)(x) << L1_PAGETABLE_SHIFT)
-#define PHYS_PFN(x) ((x) >> L1_PAGETABLE_SHIFT)
-
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
-#ifndef __ASSEMBLY__
-/* Definitions for machine and pseudophysical addresses. */
-#ifdef __i386__
-typedef unsigned long long paddr_t;
-typedef unsigned long long maddr_t;
-#else
-typedef unsigned long paddr_t;
-typedef unsigned long maddr_t;
-#endif
-
-extern unsigned long *phys_to_machine_mapping;
-extern char _text, _etext, _erodata, _edata, _end;
-extern unsigned long mfn_zero;
-#define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
-static __inline__ maddr_t phys_to_machine(paddr_t phys)
-{
- maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
- machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK);
- return machine;
-}
-
-#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
-static __inline__ paddr_t machine_to_phys(maddr_t machine)
-{
- paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
- phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
- return phys;
-}
-#endif
-
-#define VIRT_START ((unsigned long)&_text)
-
-#define to_phys(x) ((unsigned long)(x)-VIRT_START)
-#define to_virt(x) ((void *)((unsigned long)(x)+VIRT_START))
-
-#define virt_to_pfn(_virt) (PFN_DOWN(to_phys(_virt)))
-#define virt_to_mfn(_virt) (pfn_to_mfn(virt_to_pfn(_virt)))
-#define mach_to_virt(_mach) (to_virt(machine_to_phys(_mach)))
-#define virt_to_mach(_virt) (phys_to_machine(to_phys(_virt)))
-#define mfn_to_virt(_mfn) (to_virt(mfn_to_pfn(_mfn) << PAGE_SHIFT))
-#define pfn_to_virt(_pfn) (to_virt((_pfn) << PAGE_SHIFT))
-
-/* Pagetable walking. */
-#define pte_to_mfn(_pte) (((_pte) & (PADDR_MASK&PAGE_MASK)) >> L1_PAGETABLE_SHIFT)
-#define pte_to_virt(_pte) to_virt(mfn_to_pfn(pte_to_mfn(_pte)) << PAGE_SHIFT)
-
-
-#define PT_BASE ((pgentry_t *)start_info.pt_base)
-
-#ifdef __x86_64__
-#define virtual_to_l3(_virt) ((pgentry_t *)pte_to_virt(PT_BASE[l4_table_offset(_virt)]))
-#else
-#define virtual_to_l3(_virt) PT_BASE
-#endif
-
-#define virtual_to_l2(_virt) ({ \
- unsigned long __virt2 = (_virt); \
- (pgentry_t *) pte_to_virt(virtual_to_l3(__virt2)[l3_table_offset(__virt2)]); \
-})
-
-#define virtual_to_l1(_virt) ({ \
- unsigned long __virt1 = (_virt); \
- (pgentry_t *) pte_to_virt(virtual_to_l2(__virt1)[l2_table_offset(__virt1)]); \
-})
-
-#define virtual_to_pte(_virt) ({ \
- unsigned long __virt0 = (unsigned long) (_virt); \
- virtual_to_l1(__virt0)[l1_table_offset(__virt0)]; \
-})
-#define virtual_to_mfn(_virt) pte_to_mfn(virtual_to_pte(_virt))
-
-#define map_frames(f, n) map_frames_ex(f, n, 1, 0, 1, DOMID_SELF, NULL, L1_PROT)
-#define map_zero(n, a) map_frames_ex(&mfn_zero, n, 0, 0, a, DOMID_SELF, NULL, L1_PROT_RO)
-#define do_map_zero(start, n) do_map_frames(start, &mfn_zero, n, 0, 0, DOMID_SELF, NULL, L1_PROT_RO)
-
-pgentry_t *need_pgt(unsigned long addr);
-
-#endif /* _ARCH_MM_H_ */
+++ /dev/null
-
-#ifndef __ARCH_SCHED_H__
-#define __ARCH_SCHED_H__
-
-#include "arch_limits.h"
-
-static inline struct thread* get_current(void)
-{
- struct thread **current;
-#ifdef __i386__
- register unsigned long sp asm("esp");
-#else
- register unsigned long sp asm("rsp");
-#endif
- current = (void *)(unsigned long)(sp & ~(__STACK_SIZE-1));
- return *current;
-}
-
-extern void __arch_switch_threads(unsigned long *prevctx, unsigned long *nextctx);
-
-#define arch_switch_threads(prev,next) __arch_switch_threads(&(prev)->sp, &(next)->sp)
-
-
-
-#endif /* __ARCH_SCHED_H__ */
+++ /dev/null
-
-
-#ifndef __ARCH_ASM_SPINLOCK_H
-#define __ARCH_ASM_SPINLOCK_H
-
-#include <mini-os/lib.h>
-#include "os.h"
-
-
-#define ARCH_SPIN_LOCK_UNLOCKED { 1 }
-
-/*
- * Simple spin lock operations. There are two variants, one clears IRQ's
- * on the local processor, one does not.
- *
- * We make no fairness assumptions. They have a cost.
- */
-
-#define arch_spin_is_locked(x) (*(volatile signed char *)(&(x)->slock) <= 0)
-#define arch_spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
-
-#define spin_lock_string \
- "1:\n" \
- LOCK \
- "decb %0\n\t" \
- "jns 3f\n" \
- "2:\t" \
- "rep;nop\n\t" \
- "cmpb $0,%0\n\t" \
- "jle 2b\n\t" \
- "jmp 1b\n" \
- "3:\n\t"
-
-#define spin_lock_string_flags \
- "1:\n" \
- LOCK \
- "decb %0\n\t" \
- "jns 4f\n\t" \
- "2:\t" \
- "testl $0x200, %1\n\t" \
- "jz 3f\n\t" \
- "#sti\n\t" \
- "3:\t" \
- "rep;nop\n\t" \
- "cmpb $0, %0\n\t" \
- "jle 3b\n\t" \
- "#cli\n\t" \
- "jmp 1b\n" \
- "4:\n\t"
-
-/*
- * This works. Despite all the confusion.
- * (except on PPro SMP or if we are using OOSTORE)
- * (PPro errata 66, 92)
- */
-
-#define spin_unlock_string \
- "xchgb %b0, %1" \
- :"=q" (oldval), "=m" (lock->slock) \
- :"0" (oldval) : "memory"
-
-static inline void _raw_spin_unlock(spinlock_t *lock)
-{
- char oldval = ARCH_SPIN_LOCK_UNLOCKED;
- __asm__ __volatile__(
- spin_unlock_string
- );
-}
-
-static inline int _raw_spin_trylock(spinlock_t *lock)
-{
- char oldval;
- __asm__ __volatile__(
- "xchgb %b0,%1\n"
- :"=q" (oldval), "=m" (lock->slock)
- :"0" (0) : "memory");
- return oldval > 0;
-}
-
-static inline void _raw_spin_lock(spinlock_t *lock)
-{
- __asm__ __volatile__(
- spin_lock_string
- :"=m" (lock->slock) : : "memory");
-}
-
-static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
-{
- __asm__ __volatile__(
- spin_lock_string_flags
- :"=m" (lock->slock) : "r" (flags) : "memory");
-}
-
-#endif
+++ /dev/null
-/******************************************************************************
- * os.h
- *
- * random collection of macros and definition
- */
-
-#ifndef _OS_H_
-#define _OS_H_
-
-#define smp_processor_id() 0
-
-
-#ifndef __ASSEMBLY__
-#include <mini-os/compiler.h>
-#include <mini-os/types.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/kernel.h>
-#include <xen/xsm/flask_op.h>
-
-#define USED __attribute__ ((used))
-
-#define BUG do_exit
-
-#endif
-#include <xen/xen.h>
-
-
-
-#define __KERNEL_CS FLAT_KERNEL_CS
-#define __KERNEL_DS FLAT_KERNEL_DS
-#define __KERNEL_SS FLAT_KERNEL_SS
-
-#define TRAP_divide_error 0
-#define TRAP_debug 1
-#define TRAP_nmi 2
-#define TRAP_int3 3
-#define TRAP_overflow 4
-#define TRAP_bounds 5
-#define TRAP_invalid_op 6
-#define TRAP_no_device 7
-#define TRAP_double_fault 8
-#define TRAP_copro_seg 9
-#define TRAP_invalid_tss 10
-#define TRAP_no_segment 11
-#define TRAP_stack_error 12
-#define TRAP_gp_fault 13
-#define TRAP_page_fault 14
-#define TRAP_spurious_int 15
-#define TRAP_copro_error 16
-#define TRAP_alignment_check 17
-#define TRAP_machine_check 18
-#define TRAP_simd_error 19
-#define TRAP_deferred_nmi 31
-
-/* Everything below this point is not included by assembler (.S) files. */
-#ifndef __ASSEMBLY__
-
-extern shared_info_t *HYPERVISOR_shared_info;
-
-void trap_init(void);
-void trap_fini(void);
-
-void arch_fini(void);
-
-
-
-
-
-/*
- * The use of 'barrier' in the following reflects their use as local-lock
- * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following
- * critical operations are executed. All critical operations must complete
- * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also
- * includes these barriers, for example.
- */
-
-#define __cli() \
-do { \
- vcpu_info_t *_vcpu; \
- _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
- _vcpu->evtchn_upcall_mask = 1; \
- barrier(); \
-} while (0)
-
-#define __sti() \
-do { \
- vcpu_info_t *_vcpu; \
- barrier(); \
- _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
- _vcpu->evtchn_upcall_mask = 0; \
- barrier(); /* unmask then check (avoid races) */ \
- if ( unlikely(_vcpu->evtchn_upcall_pending) ) \
- force_evtchn_callback(); \
-} while (0)
-
-#define __save_flags(x) \
-do { \
- vcpu_info_t *_vcpu; \
- _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
- (x) = _vcpu->evtchn_upcall_mask; \
-} while (0)
-
-#define __restore_flags(x) \
-do { \
- vcpu_info_t *_vcpu; \
- barrier(); \
- _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
- if ((_vcpu->evtchn_upcall_mask = (x)) == 0) { \
- barrier(); /* unmask then check (avoid races) */ \
- if ( unlikely(_vcpu->evtchn_upcall_pending) ) \
- force_evtchn_callback(); \
- }\
-} while (0)
-
-#define safe_halt() ((void)0)
-
-#define __save_and_cli(x) \
-do { \
- vcpu_info_t *_vcpu; \
- _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; \
- (x) = _vcpu->evtchn_upcall_mask; \
- _vcpu->evtchn_upcall_mask = 1; \
- barrier(); \
-} while (0)
-
-#define local_irq_save(x) __save_and_cli(x)
-#define local_irq_restore(x) __restore_flags(x)
-#define local_save_flags(x) __save_flags(x)
-#define local_irq_disable() __cli()
-#define local_irq_enable() __sti()
-
-#define irqs_disabled() \
- HYPERVISOR_shared_info->vcpu_info[smp_processor_id()].evtchn_upcall_mask
-
-/* This is a barrier for the compiler only, NOT the processor! */
-#define barrier() __asm__ __volatile__("": : :"memory")
-
-#if defined(__i386__)
-#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
-#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
-#define wmb() __asm__ __volatile__ ("": : :"memory")
-#elif defined(__x86_64__)
-#define mb() __asm__ __volatile__ ("mfence":::"memory")
-#define rmb() __asm__ __volatile__ ("lfence":::"memory")
-#define wmb() __asm__ __volatile__ ("sfence" ::: "memory") /* From CONFIG_UNORDERED_IO (linux) */
-#endif
-
-
-#define LOCK_PREFIX ""
-#define LOCK ""
-#define ADDR (*(volatile long *) addr)
-/*
- * Make sure gcc doesn't try to be clever and move things around
- * on us. We need to use _exactly_ the address the user gave us,
- * not some alias that contains the same information.
- */
-typedef struct { volatile int counter; } atomic_t;
-
-
-/************************** i386 *******************************/
-#ifdef __INSIDE_MINIOS__
-#if defined (__i386__)
-
-#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((struct __xchg_dummy *)(x))
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
- switch (size) {
- case 1:
- __asm__ __volatile__("xchgb %b0,%1"
- :"=q" (x)
- :"m" (*__xg(ptr)), "0" (x)
- :"memory");
- break;
- case 2:
- __asm__ __volatile__("xchgw %w0,%1"
- :"=r" (x)
- :"m" (*__xg(ptr)), "0" (x)
- :"memory");
- break;
- case 4:
- __asm__ __volatile__("xchgl %0,%1"
- :"=r" (x)
- :"m" (*__xg(ptr)), "0" (x)
- :"memory");
- break;
- }
- return x;
-}
-
-/**
- * test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to clear
- * @addr: Address to count from
- *
- * This operation is atomic and cannot be reordered.
- * It can be reorderdered on other architectures other than x86.
- * It also implies a memory barrier.
- */
-static inline int test_and_clear_bit(int nr, volatile unsigned long * addr)
-{
- int oldbit;
-
- __asm__ __volatile__( LOCK
- "btrl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
- :"Ir" (nr) : "memory");
- return oldbit;
-}
-
-static inline int constant_test_bit(int nr, const volatile unsigned long *addr)
-{
- return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0;
-}
-
-static inline int variable_test_bit(int nr, const volatile unsigned long * addr)
-{
- int oldbit;
-
- __asm__ __volatile__(
- "btl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit)
- :"m" (ADDR),"Ir" (nr));
- return oldbit;
-}
-
-#define test_bit(nr,addr) \
-(__builtin_constant_p(nr) ? \
- constant_test_bit((nr),(addr)) : \
- variable_test_bit((nr),(addr)))
-
-/**
- * set_bit - Atomically set a bit in memory
- * @nr: the bit to set
- * @addr: the address to start counting from
- *
- * This function is atomic and may not be reordered. See __set_bit()
- * if you do not require the atomic guarantees.
- *
- * Note: there are no guarantees that this function will not be reordered
- * on non x86 architectures, so if you are writting portable code,
- * make sure not to rely on its reordering guarantees.
- *
- * Note that @nr may be almost arbitrarily large; this function is not
- * restricted to acting on a single-word quantity.
- */
-static inline void set_bit(int nr, volatile unsigned long * addr)
-{
- __asm__ __volatile__( LOCK
- "btsl %1,%0"
- :"=m" (ADDR)
- :"Ir" (nr));
-}
-
-/**
- * clear_bit - Clears a bit in memory
- * @nr: Bit to clear
- * @addr: Address to start counting from
- *
- * clear_bit() is atomic and may not be reordered. However, it does
- * not contain a memory barrier, so if it is used for locking purposes,
- * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
- * in order to ensure changes are visible on other processors.
- */
-static inline void clear_bit(int nr, volatile unsigned long * addr)
-{
- __asm__ __volatile__( LOCK
- "btrl %1,%0"
- :"=m" (ADDR)
- :"Ir" (nr));
-}
-
-/**
- * __ffs - find first bit in word.
- * @word: The word to search
- *
- * Undefined if no bit exists, so code should check against 0 first.
- */
-static inline unsigned long __ffs(unsigned long word)
-{
- __asm__("bsfl %1,%0"
- :"=r" (word)
- :"rm" (word));
- return word;
-}
-
-
-/*
- * These have to be done with inline assembly: that way the bit-setting
- * is guaranteed to be atomic. All bit operations return 0 if the bit
- * was cleared before the operation and != 0 if it was not.
- *
- * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
- */
-#define ADDR (*(volatile long *) addr)
-
-#define rdtscll(val) \
- __asm__ __volatile__("rdtsc" : "=A" (val))
-
-
-
-#elif defined(__x86_64__)/* ifdef __i386__ */
-/************************** x86_84 *******************************/
-
-#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
-#define __xg(x) ((volatile long *)(x))
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
- switch (size) {
- case 1:
- __asm__ __volatile__("xchgb %b0,%1"
- :"=q" (x)
- :"m" (*__xg(ptr)), "0" (x)
- :"memory");
- break;
- case 2:
- __asm__ __volatile__("xchgw %w0,%1"
- :"=r" (x)
- :"m" (*__xg(ptr)), "0" (x)
- :"memory");
- break;
- case 4:
- __asm__ __volatile__("xchgl %k0,%1"
- :"=r" (x)
- :"m" (*__xg(ptr)), "0" (x)
- :"memory");
- break;
- case 8:
- __asm__ __volatile__("xchgq %0,%1"
- :"=r" (x)
- :"m" (*__xg(ptr)), "0" (x)
- :"memory");
- break;
- }
- return x;
-}
-
-/**
- * test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to clear
- * @addr: Address to count from
- *
- * This operation is atomic and cannot be reordered.
- * It also implies a memory barrier.
- */
-static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
-{
- int oldbit;
-
- __asm__ __volatile__( LOCK_PREFIX
- "btrl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
- :"dIr" (nr) : "memory");
- return oldbit;
-}
-
-static __inline__ int constant_test_bit(int nr, const volatile void * addr)
-{
- return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
-}
-
-static __inline__ int variable_test_bit(int nr, volatile const void * addr)
-{
- int oldbit;
-
- __asm__ __volatile__(
- "btl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit)
- :"m" (ADDR),"dIr" (nr));
- return oldbit;
-}
-
-#define test_bit(nr,addr) \
-(__builtin_constant_p(nr) ? \
- constant_test_bit((nr),(addr)) : \
- variable_test_bit((nr),(addr)))
-
-
-/**
- * set_bit - Atomically set a bit in memory
- * @nr: the bit to set
- * @addr: the address to start counting from
- *
- * This function is atomic and may not be reordered. See __set_bit()
- * if you do not require the atomic guarantees.
- * Note that @nr may be almost arbitrarily large; this function is not
- * restricted to acting on a single-word quantity.
- */
-static __inline__ void set_bit(int nr, volatile void * addr)
-{
- __asm__ __volatile__( LOCK_PREFIX
- "btsl %1,%0"
- :"=m" (ADDR)
- :"dIr" (nr) : "memory");
-}
-
-/**
- * clear_bit - Clears a bit in memory
- * @nr: Bit to clear
- * @addr: Address to start counting from
- *
- * clear_bit() is atomic and may not be reordered. However, it does
- * not contain a memory barrier, so if it is used for locking purposes,
- * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
- * in order to ensure changes are visible on other processors.
- */
-static __inline__ void clear_bit(int nr, volatile void * addr)
-{
- __asm__ __volatile__( LOCK_PREFIX
- "btrl %1,%0"
- :"=m" (ADDR)
- :"dIr" (nr));
-}
-
-/**
- * __ffs - find first bit in word.
- * @word: The word to search
- *
- * Undefined if no bit exists, so code should check against 0 first.
- */
-static __inline__ unsigned long __ffs(unsigned long word)
-{
- __asm__("bsfq %1,%0"
- :"=r" (word)
- :"rm" (word));
- return word;
-}
-
-#define ADDR (*(volatile long *) addr)
-
-#define rdtscll(val) do { \
- unsigned int __a,__d; \
- asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
- (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
-} while(0)
-
-#define wrmsr(msr,val1,val2) \
- __asm__ __volatile__("wrmsr" \
- : /* no outputs */ \
- : "c" (msr), "a" (val1), "d" (val2))
-
-#define wrmsrl(msr,val) wrmsr(msr,(uint32_t)((uint64_t)(val)),((uint64_t)(val))>>32)
-
-
-#else /* ifdef __x86_64__ */
-#error "Unsupported architecture"
-#endif
-#endif /* ifdef __INSIDE_MINIOS */
-
-/********************* common i386 and x86_64 ****************************/
-struct __synch_xchg_dummy { unsigned long a[100]; };
-#define __synch_xg(x) ((struct __synch_xchg_dummy *)(x))
-
-#define synch_cmpxchg(ptr, old, new) \
-((__typeof__(*(ptr)))__synch_cmpxchg((ptr),\
- (unsigned long)(old), \
- (unsigned long)(new), \
- sizeof(*(ptr))))
-
-static inline unsigned long __synch_cmpxchg(volatile void *ptr,
- unsigned long old,
- unsigned long new, int size)
-{
- unsigned long prev;
- switch (size) {
- case 1:
- __asm__ __volatile__("lock; cmpxchgb %b1,%2"
- : "=a"(prev)
- : "q"(new), "m"(*__synch_xg(ptr)),
- "0"(old)
- : "memory");
- return prev;
- case 2:
- __asm__ __volatile__("lock; cmpxchgw %w1,%2"
- : "=a"(prev)
- : "r"(new), "m"(*__synch_xg(ptr)),
- "0"(old)
- : "memory");
- return prev;
-#ifdef __x86_64__
- case 4:
- __asm__ __volatile__("lock; cmpxchgl %k1,%2"
- : "=a"(prev)
- : "r"(new), "m"(*__synch_xg(ptr)),
- "0"(old)
- : "memory");
- return prev;
- case 8:
- __asm__ __volatile__("lock; cmpxchgq %1,%2"
- : "=a"(prev)
- : "r"(new), "m"(*__synch_xg(ptr)),
- "0"(old)
- : "memory");
- return prev;
-#else
- case 4:
- __asm__ __volatile__("lock; cmpxchgl %1,%2"
- : "=a"(prev)
- : "r"(new), "m"(*__synch_xg(ptr)),
- "0"(old)
- : "memory");
- return prev;
-#endif
- }
- return old;
-}
-
-
-static __inline__ void synch_set_bit(int nr, volatile void * addr)
-{
- __asm__ __volatile__ (
- "lock btsl %1,%0"
- : "=m" (ADDR) : "Ir" (nr) : "memory" );
-}
-
-static __inline__ void synch_clear_bit(int nr, volatile void * addr)
-{
- __asm__ __volatile__ (
- "lock btrl %1,%0"
- : "=m" (ADDR) : "Ir" (nr) : "memory" );
-}
-
-static __inline__ int synch_test_and_set_bit(int nr, volatile void * addr)
-{
- int oldbit;
- __asm__ __volatile__ (
- "lock btsl %2,%1\n\tsbbl %0,%0"
- : "=r" (oldbit), "=m" (ADDR) : "Ir" (nr) : "memory");
- return oldbit;
-}
-
-static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr)
-{
- int oldbit;
- __asm__ __volatile__ (
- "lock btrl %2,%1\n\tsbbl %0,%0"
- : "=r" (oldbit), "=m" (ADDR) : "Ir" (nr) : "memory");
- return oldbit;
-}
-
-static __inline__ int synch_const_test_bit(int nr, const volatile void * addr)
-{
- return ((1UL << (nr & 31)) &
- (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
-}
-
-static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
-{
- int oldbit;
- __asm__ __volatile__ (
- "btl %2,%1\n\tsbbl %0,%0"
- : "=r" (oldbit) : "m" (ADDR), "Ir" (nr) );
- return oldbit;
-}
-
-#define synch_test_bit(nr,addr) \
-(__builtin_constant_p(nr) ? \
- synch_const_test_bit((nr),(addr)) : \
- synch_var_test_bit((nr),(addr)))
-
-static inline int
-HYPERVISOR_xsm_op(
- struct xen_flask_op *op)
-{
- return _hypercall1(int, xsm_op, op);
-}
-
-#undef ADDR
-
-#endif /* not assembly */
-#endif /* _OS_H_ */
+++ /dev/null
-/*
- ****************************************************************************
- * (C) 2005 - Grzegorz Milos - Intel Reseach Cambridge
- ****************************************************************************
- *
- * File: traps.h
- * Author: Grzegorz Milos (gm281@cam.ac.uk)
- *
- * Date: Jun 2005
- *
- * Environment: Xen Minimal OS
- * Description: Deals with traps
- *
- ****************************************************************************
- */
-
-#ifndef _TRAPS_H_
-#define _TRAPS_H_
-
-#ifdef __i386__
-struct pt_regs {
- long ebx;
- long ecx;
- long edx;
- long esi;
- long edi;
- long ebp;
- long eax;
- int xds;
- int xes;
- long orig_eax;
- long eip;
- int xcs;
- long eflags;
- long esp;
- int xss;
-};
-#elif __x86_64__
-
-struct pt_regs {
- unsigned long r15;
- unsigned long r14;
- unsigned long r13;
- unsigned long r12;
- unsigned long rbp;
- unsigned long rbx;
-/* arguments: non interrupts/non tracing syscalls only save upto here*/
- unsigned long r11;
- unsigned long r10;
- unsigned long r9;
- unsigned long r8;
- unsigned long rax;
- unsigned long rcx;
- unsigned long rdx;
- unsigned long rsi;
- unsigned long rdi;
- unsigned long orig_rax;
-/* end of arguments */
-/* cpu exception frame or undefined */
- unsigned long rip;
- unsigned long cs;
- unsigned long eflags;
- unsigned long rsp;
- unsigned long ss;
-/* top of stack page */
-};
-
-
-#endif
-
-void dump_regs(struct pt_regs *regs);
-void stack_walk(void);
-
-#define TRAP_PF_PROT 0x1
-#define TRAP_PF_WRITE 0x2
-#define TRAP_PF_USER 0x4
-
-#endif /* _TRAPS_H_ */
+++ /dev/null
-#define __WORDSIZE 32
+++ /dev/null
-/******************************************************************************
- * hypercall-x86_32.h
- *
- * Copied from XenLinux.
- *
- * Copyright (c) 2002-2004, K A Fraser
- *
- * This file may be distributed separately from the Linux kernel, or
- * incorporated into other software packages, subject to the following license:
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this source file (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef __HYPERCALL_X86_32_H__
-#define __HYPERCALL_X86_32_H__
-
-#include <xen/xen.h>
-#include <xen/sched.h>
-#include <xen/nmi.h>
-#include <mini-os/mm.h>
-
-typedef struct { unsigned long pte_low, pte_high; } pte_t;
-
-#define __pte(x) ({ unsigned long long _x = (x); \
- ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
-
-#define __STR(x) #x
-#define STR(x) __STR(x)
-
-extern char hypercall_page[PAGE_SIZE];
-
-#define _hypercall0(type, name) \
-({ \
- long __res; \
- asm volatile ( \
- "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
- : "=a" (__res) \
- : \
- : "memory" ); \
- (type)__res; \
-})
-
-#define _hypercall1(type, name, a1) \
-({ \
- long __res, __ign1; \
- asm volatile ( \
- "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
- : "=a" (__res), "=b" (__ign1) \
- : "1" ((long)(a1)) \
- : "memory" ); \
- (type)__res; \
-})
-
-#define _hypercall2(type, name, a1, a2) \
-({ \
- long __res, __ign1, __ign2; \
- asm volatile ( \
- "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
- : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \
- : "1" ((long)(a1)), "2" ((long)(a2)) \
- : "memory" ); \
- (type)__res; \
-})
-
-#define _hypercall3(type, name, a1, a2, a3) \
-({ \
- long __res, __ign1, __ign2, __ign3; \
- asm volatile ( \
- "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
- : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
- "=d" (__ign3) \
- : "1" ((long)(a1)), "2" ((long)(a2)), \
- "3" ((long)(a3)) \
- : "memory" ); \
- (type)__res; \
-})
-
-#define _hypercall4(type, name, a1, a2, a3, a4) \
-({ \
- long __res, __ign1, __ign2, __ign3, __ign4; \
- asm volatile ( \
- "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
- : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
- "=d" (__ign3), "=S" (__ign4) \
- : "1" ((long)(a1)), "2" ((long)(a2)), \
- "3" ((long)(a3)), "4" ((long)(a4)) \
- : "memory" ); \
- (type)__res; \
-})
-
-#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
-({ \
- long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \
- asm volatile ( \
- "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
- : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
- "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \
- : "1" ((long)(a1)), "2" ((long)(a2)), \
- "3" ((long)(a3)), "4" ((long)(a4)), \
- "5" ((long)(a5)) \
- : "memory" ); \
- (type)__res; \
-})
-
-static inline int
-HYPERVISOR_set_trap_table(
- trap_info_t *table)
-{
- return _hypercall1(int, set_trap_table, table);
-}
-
-static inline int
-HYPERVISOR_mmu_update(
- mmu_update_t *req, int count, int *success_count, domid_t domid)
-{
- return _hypercall4(int, mmu_update, req, count, success_count, domid);
-}
-
-static inline int
-HYPERVISOR_mmuext_op(
- struct mmuext_op *op, int count, int *success_count, domid_t domid)
-{
- return _hypercall4(int, mmuext_op, op, count, success_count, domid);
-}
-
-static inline int
-HYPERVISOR_set_gdt(
- unsigned long *frame_list, int entries)
-{
- return _hypercall2(int, set_gdt, frame_list, entries);
-}
-
-static inline int
-HYPERVISOR_stack_switch(
- unsigned long ss, unsigned long esp)
-{
- return _hypercall2(int, stack_switch, ss, esp);
-}
-
-static inline int
-HYPERVISOR_set_callbacks(
- unsigned long event_selector, unsigned long event_address,
- unsigned long failsafe_selector, unsigned long failsafe_address)
-{
- return _hypercall4(int, set_callbacks,
- event_selector, event_address,
- failsafe_selector, failsafe_address);
-}
-
-static inline int
-HYPERVISOR_fpu_taskswitch(
- int set)
-{
- return _hypercall1(int, fpu_taskswitch, set);
-}
-
-static inline int
-HYPERVISOR_sched_op(
- int cmd, void *arg)
-{
- return _hypercall2(int, sched_op, cmd, arg);
-}
-
-static inline int
-HYPERVISOR_shutdown(
- unsigned int reason)
-{
- struct sched_shutdown shutdown = { .reason = reason };
- return _hypercall2(int, sched_op, SCHEDOP_shutdown, &shutdown);
-}
-
-static inline long
-HYPERVISOR_set_timer_op(
- uint64_t timeout)
-{
- unsigned long timeout_hi = (unsigned long)(timeout>>32);
- unsigned long timeout_lo = (unsigned long)timeout;
- return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
-}
-
-static inline int
-HYPERVISOR_set_debugreg(
- int reg, unsigned long value)
-{
- return _hypercall2(int, set_debugreg, reg, value);
-}
-
-static inline unsigned long
-HYPERVISOR_get_debugreg(
- int reg)
-{
- return _hypercall1(unsigned long, get_debugreg, reg);
-}
-
-static inline int
-HYPERVISOR_update_descriptor(
- uint64_t ma, uint64_t desc)
-{
- return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
-}
-
-static inline int
-HYPERVISOR_memory_op(
- unsigned int cmd, void *arg)
-{
- return _hypercall2(int, memory_op, cmd, arg);
-}
-
-static inline int
-HYPERVISOR_multicall(
- void *call_list, int nr_calls)
-{
- return _hypercall2(int, multicall, call_list, nr_calls);
-}
-
-static inline int
-HYPERVISOR_update_va_mapping(
- unsigned long va, pte_t new_val, unsigned long flags)
-{
- return _hypercall4(int, update_va_mapping, va,
- new_val.pte_low, new_val.pte_high, flags);
-}
-
-static inline int
-HYPERVISOR_event_channel_op(
- int cmd, void *op)
-{
- return _hypercall2(int, event_channel_op, cmd, op);
-}
-
-static inline int
-HYPERVISOR_xen_version(
- int cmd, void *arg)
-{
- return _hypercall2(int, xen_version, cmd, arg);
-}
-
-static inline int
-HYPERVISOR_console_io(
- int cmd, int count, char *str)
-{
- return _hypercall3(int, console_io, cmd, count, str);
-}
-
-static inline int
-HYPERVISOR_physdev_op(
- int cmd, void *physdev_op)
-{
- return _hypercall2(int, physdev_op, cmd, physdev_op);
-}
-
-static inline int
-HYPERVISOR_grant_table_op(
- unsigned int cmd, void *uop, unsigned int count)
-{
- return _hypercall3(int, grant_table_op, cmd, uop, count);
-}
-
-static inline int
-HYPERVISOR_update_va_mapping_otherdomain(
- unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
-{
- return _hypercall5(int, update_va_mapping_otherdomain, va,
- new_val.pte_low, new_val.pte_high, flags, domid);
-}
-
-static inline int
-HYPERVISOR_vm_assist(
- unsigned int cmd, unsigned int type)
-{
- return _hypercall2(int, vm_assist, cmd, type);
-}
-
-static inline int
-HYPERVISOR_vcpu_op(
- int cmd, int vcpuid, void *extra_args)
-{
- return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
-}
-
-static inline int
-HYPERVISOR_suspend(
- unsigned long srec)
-{
- return _hypercall3(int, sched_op, SCHEDOP_shutdown,
- SHUTDOWN_suspend, srec);
-}
-
-static inline int
-HYPERVISOR_nmi_op(
- unsigned long op,
- unsigned long arg)
-{
- return _hypercall2(int, nmi_op, op, arg);
-}
-
-static inline int
-HYPERVISOR_sysctl(
- unsigned long op)
-{
- return _hypercall1(int, sysctl, op);
-}
-
-static inline int
-HYPERVISOR_domctl(
- unsigned long op)
-{
- return _hypercall1(int, domctl, op);
-}
-
-#endif /* __HYPERCALL_X86_32_H__ */
-
-/*
- * Local variables:
- * c-file-style: "linux"
- * indent-tabs-mode: t
- * c-indent-level: 8
- * c-basic-offset: 8
- * tab-width: 8
- * End:
- */
+++ /dev/null
-#define __WORDSIZE 64
-#define __WORDSIZE_COMPAT32 1
+++ /dev/null
-/******************************************************************************
- * hypercall-x86_64.h
- *
- * Copied from XenLinux.
- *
- * Copyright (c) 2002-2004, K A Fraser
- *
- * 64-bit updates:
- * Benjamin Liu <benjamin.liu@intel.com>
- * Jun Nakajima <jun.nakajima@intel.com>
- *
- * This file may be distributed separately from the Linux kernel, or
- * incorporated into other software packages, subject to the following license:
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this source file (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef __HYPERCALL_X86_64_H__
-#define __HYPERCALL_X86_64_H__
-
-#include <xen/xen.h>
-#include <xen/sched.h>
-#include <mini-os/mm.h>
-
-typedef struct { unsigned long pte; } pte_t;
-
-#define __pte(x) ((pte_t) { (x) } )
-
-#define __STR(x) #x
-#define STR(x) __STR(x)
-
-extern char hypercall_page[PAGE_SIZE];
-
-#define _hypercall0(type, name) \
-({ \
- long __res; \
- asm volatile ( \
- "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
- : "=a" (__res) \
- : \
- : "memory" ); \
- (type)__res; \
-})
-
-#define _hypercall1(type, name, a1) \
-({ \
- long __res, __ign1; \
- asm volatile ( \
- "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
- : "=a" (__res), "=D" (__ign1) \
- : "1" ((long)(a1)) \
- : "memory" ); \
- (type)__res; \
-})
-
-#define _hypercall2(type, name, a1, a2) \
-({ \
- long __res, __ign1, __ign2; \
- asm volatile ( \
- "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
- : "=a" (__res), "=D" (__ign1), "=S" (__ign2) \
- : "1" ((long)(a1)), "2" ((long)(a2)) \
- : "memory" ); \
- (type)__res; \
-})
-
-#define _hypercall3(type, name, a1, a2, a3) \
-({ \
- long __res, __ign1, __ign2, __ign3; \
- asm volatile ( \
- "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
- : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \
- "=d" (__ign3) \
- : "1" ((long)(a1)), "2" ((long)(a2)), \
- "3" ((long)(a3)) \
- : "memory" ); \
- (type)__res; \
-})
-
-#define _hypercall4(type, name, a1, a2, a3, a4) \
-({ \
- long __res, __ign1, __ign2, __ign3; \
- asm volatile ( \
- "movq %7,%%r10; " \
- "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
- : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \
- "=d" (__ign3) \
- : "1" ((long)(a1)), "2" ((long)(a2)), \
- "3" ((long)(a3)), "g" ((long)(a4)) \
- : "memory", "r10" ); \
- (type)__res; \
-})
-
-#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
-({ \
- long __res, __ign1, __ign2, __ign3; \
- asm volatile ( \
- "movq %7,%%r10; movq %8,%%r8; " \
- "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
- : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \
- "=d" (__ign3) \
- : "1" ((long)(a1)), "2" ((long)(a2)), \
- "3" ((long)(a3)), "g" ((long)(a4)), \
- "g" ((long)(a5)) \
- : "memory", "r10", "r8" ); \
- (type)__res; \
-})
-
-static inline int
-HYPERVISOR_set_trap_table(
- trap_info_t *table)
-{
- return _hypercall1(int, set_trap_table, table);
-}
-
-static inline int
-HYPERVISOR_mmu_update(
- mmu_update_t *req, int count, int *success_count, domid_t domid)
-{
- return _hypercall4(int, mmu_update, req, count, success_count, domid);
-}
-
-static inline int
-HYPERVISOR_mmuext_op(
- struct mmuext_op *op, int count, int *success_count, domid_t domid)
-{
- return _hypercall4(int, mmuext_op, op, count, success_count, domid);
-}
-
-static inline int
-HYPERVISOR_set_gdt(
- unsigned long *frame_list, int entries)
-{
- return _hypercall2(int, set_gdt, frame_list, entries);
-}
-
-static inline int
-HYPERVISOR_stack_switch(
- unsigned long ss, unsigned long esp)
-{
- return _hypercall2(int, stack_switch, ss, esp);
-}
-
-static inline int
-HYPERVISOR_set_callbacks(
- unsigned long event_address, unsigned long failsafe_address,
- unsigned long syscall_address)
-{
- return _hypercall3(int, set_callbacks,
- event_address, failsafe_address, syscall_address);
-}
-
-static inline int
-HYPERVISOR_fpu_taskswitch(
- int set)
-{
- return _hypercall1(int, fpu_taskswitch, set);
-}
-
-static inline int
-HYPERVISOR_sched_op(
- int cmd, void *arg)
-{
- return _hypercall2(int, sched_op, cmd, arg);
-}
-
-static inline int
-HYPERVISOR_shutdown(
- unsigned int reason)
-{
- struct sched_shutdown shutdown = { .reason = reason };
- return _hypercall2(int, sched_op, SCHEDOP_shutdown, &shutdown);
-}
-
-static inline long
-HYPERVISOR_set_timer_op(
- uint64_t timeout)
-{
- return _hypercall1(long, set_timer_op, timeout);
-}
-
-static inline int
-HYPERVISOR_set_debugreg(
- int reg, unsigned long value)
-{
- return _hypercall2(int, set_debugreg, reg, value);
-}
-
-static inline unsigned long
-HYPERVISOR_get_debugreg(
- int reg)
-{
- return _hypercall1(unsigned long, get_debugreg, reg);
-}
-
-static inline int
-HYPERVISOR_update_descriptor(
- unsigned long ma, unsigned long word)
-{
- return _hypercall2(int, update_descriptor, ma, word);
-}
-
-static inline int
-HYPERVISOR_memory_op(
- unsigned int cmd, void *arg)
-{
- return _hypercall2(int, memory_op, cmd, arg);
-}
-
-static inline int
-HYPERVISOR_multicall(
- void *call_list, int nr_calls)
-{
- return _hypercall2(int, multicall, call_list, nr_calls);
-}
-
-static inline int
-HYPERVISOR_update_va_mapping(
- unsigned long va, pte_t new_val, unsigned long flags)
-{
- return _hypercall3(int, update_va_mapping, va, new_val.pte, flags);
-}
-
-static inline int
-HYPERVISOR_event_channel_op(
- int cmd, void *op)
-{
- return _hypercall2(int, event_channel_op, cmd, op);
-}
-
-static inline int
-HYPERVISOR_xen_version(
- int cmd, void *arg)
-{
- return _hypercall2(int, xen_version, cmd, arg);
-}
-
-static inline int
-HYPERVISOR_console_io(
- int cmd, int count, char *str)
-{
- return _hypercall3(int, console_io, cmd, count, str);
-}
-
-static inline int
-HYPERVISOR_physdev_op(
- int cmd, void *physdev_op)
-{
- return _hypercall2(int, physdev_op, cmd, physdev_op);
-}
-
-static inline int
-HYPERVISOR_grant_table_op(
- unsigned int cmd, void *uop, unsigned int count)
-{
- return _hypercall3(int, grant_table_op, cmd, uop, count);
-}
-
-static inline int
-HYPERVISOR_update_va_mapping_otherdomain(
- unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
-{
- return _hypercall4(int, update_va_mapping_otherdomain, va,
- new_val.pte, flags, domid);
-}
-
-static inline int
-HYPERVISOR_vm_assist(
- unsigned int cmd, unsigned int type)
-{
- return _hypercall2(int, vm_assist, cmd, type);
-}
-
-static inline int
-HYPERVISOR_vcpu_op(
- int cmd, int vcpuid, void *extra_args)
-{
- return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
-}
-
-static inline int
-HYPERVISOR_set_segment_base(
- int reg, unsigned long value)
-{
- return _hypercall2(int, set_segment_base, reg, value);
-}
-
-static inline int
-HYPERVISOR_suspend(
- unsigned long srec)
-{
- return _hypercall3(int, sched_op, SCHEDOP_shutdown,
- SHUTDOWN_suspend, srec);
-}
-
-static inline int
-HYPERVISOR_nmi_op(
- unsigned long op,
- unsigned long arg)
-{
- return _hypercall2(int, nmi_op, op, arg);
-}
-
-static inline int
-HYPERVISOR_sysctl(
- unsigned long op)
-{
- return _hypercall1(int, sysctl, op);
-}
-
-static inline int
-HYPERVISOR_domctl(
- unsigned long op)
-{
- return _hypercall1(int, domctl, op);
-}
-
-#endif /* __HYPERCALL_X86_64_H__ */
-
-/*
- * Local variables:
- * c-file-style: "linux"
- * indent-tabs-mode: t
- * c-indent-level: 8
- * c-basic-offset: 8
- * tab-width: 8
- * End:
- */
+++ /dev/null
-XEN NOTICE
-==========
-
-This copyright applies to all files within this subdirectory and its
-subdirectories:
- include/public/*.h
- include/public/hvm/*.h
- include/public/io/*.h
-
-The intention is that these files can be freely copied into the source
-tree of an operating system when porting that OS to run on Xen. Doing
-so does *not* cause the OS to become subject to the terms of the GPL.
-
-All other files in the Xen source distribution are covered by version
-2 of the GNU General Public License except where explicitly stated
-otherwise within individual source files.
-
- -- Keir Fraser (on behalf of the Xen team)
-
-=====================================================================
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to
-deal in the Software without restriction, including without limitation the
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
+++ /dev/null
-/******************************************************************************
- * arch-arm.h
- *
- * Guest OS interface to ARM Xen.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright 2011 (C) Citrix Systems
- */
-
-#ifndef __XEN_PUBLIC_ARCH_ARM_H__
-#define __XEN_PUBLIC_ARCH_ARM_H__
-
-/*
- * `incontents 50 arm_abi Hypercall Calling Convention
- *
- * A hypercall is issued using the ARM HVC instruction.
- *
- * A hypercall can take up to 5 arguments. These are passed in
- * registers, the first argument in x0/r0 (for arm64/arm32 guests
- * respectively irrespective of whether the underlying hypervisor is
- * 32- or 64-bit), the second argument in x1/r1, the third in x2/r2,
- * the forth in x3/r3 and the fifth in x4/r4.
- *
- * The hypercall number is passed in r12 (arm) or x16 (arm64). In both
- * cases the relevant ARM procedure calling convention specifies this
- * is an inter-procedure-call scratch register (e.g. for use in linker
- * stubs). This use does not conflict with use during a hypercall.
- *
- * The HVC ISS must contain a Xen specific TAG: XEN_HYPERCALL_TAG.
- *
- * The return value is in x0/r0.
- *
- * The hypercall will clobber x16/r12 and the argument registers used
- * by that hypercall (except r0 which is the return value) i.e. in
- * addition to x16/r12 a 2 argument hypercall will clobber x1/r1 and a
- * 4 argument hypercall will clobber x1/r1, x2/r2 and x3/r3.
- *
- * Parameter structs passed to hypercalls are laid out according to
- * the Procedure Call Standard for the ARM Architecture (AAPCS, AKA
- * EABI) and Procedure Call Standard for the ARM 64-bit Architecture
- * (AAPCS64). Where there is a conflict the 64-bit standard should be
- * used regardless of guest type. Structures which are passed as
- * hypercall arguments are always little endian.
- *
- * All memory which is shared with other entities in the system
- * (including the hypervisor and other guests) must reside in memory
- * which is mapped as Normal Inner-cacheable. This applies to:
- * - hypercall arguments passed via a pointer to guest memory.
- * - memory shared via the grant table mechanism (including PV I/O
- * rings etc).
- * - memory shared with the hypervisor (struct shared_info, struct
- * vcpu_info, the grant table, etc).
- *
- * Any Inner cache allocation strategy (Write-Back, Write-Through etc)
- * is acceptable. There is no restriction on the Outer-cacheability.
- */
-
-/*
- * `incontents 55 arm_hcall Supported Hypercalls
- *
- * Xen on ARM makes extensive use of hardware facilities and therefore
- * only a subset of the potential hypercalls are required.
- *
- * Since ARM uses second stage paging any machine/physical addresses
- * passed to hypercalls are Guest Physical Addresses (Intermediate
- * Physical Addresses) unless otherwise noted.
- *
- * The following hypercalls (and sub operations) are supported on the
- * ARM platform. Other hypercalls should be considered
- * unavailable/unsupported.
- *
- * HYPERVISOR_memory_op
- * All generic sub-operations
- *
- * HYPERVISOR_domctl
- * All generic sub-operations, with the exception of:
- * * XEN_DOMCTL_irq_permission (not yet implemented)
- *
- * HYPERVISOR_sched_op
- * All generic sub-operations, with the exception of:
- * * SCHEDOP_block -- prefer wfi hardware instruction
- *
- * HYPERVISOR_console_io
- * All generic sub-operations
- *
- * HYPERVISOR_xen_version
- * All generic sub-operations
- *
- * HYPERVISOR_event_channel_op
- * All generic sub-operations
- *
- * HYPERVISOR_physdev_op
- * No sub-operations are currenty supported
- *
- * HYPERVISOR_sysctl
- * All generic sub-operations, with the exception of:
- * * XEN_SYSCTL_page_offline_op
- * * XEN_SYSCTL_get_pmstat
- * * XEN_SYSCTL_pm_op
- *
- * HYPERVISOR_hvm_op
- * Exactly these sub-operations are supported:
- * * HVMOP_set_param
- * * HVMOP_get_param
- *
- * HYPERVISOR_grant_table_op
- * All generic sub-operations
- *
- * HYPERVISOR_vcpu_op
- * Exactly these sub-operations are supported:
- * * VCPUOP_register_vcpu_info
- * * VCPUOP_register_runstate_memory_area
- *
- *
- * Other notes on the ARM ABI:
- *
- * - struct start_info is not exported to ARM guests.
- *
- * - struct shared_info is mapped by ARM guests using the
- * HYPERVISOR_memory_op sub-op XENMEM_add_to_physmap, passing
- * XENMAPSPACE_shared_info as space parameter.
- *
- * - All the per-cpu struct vcpu_info are mapped by ARM guests using the
- * HYPERVISOR_vcpu_op sub-op VCPUOP_register_vcpu_info, including cpu0
- * struct vcpu_info.
- *
- * - The grant table is mapped using the HYPERVISOR_memory_op sub-op
- * XENMEM_add_to_physmap, passing XENMAPSPACE_grant_table as space
- * parameter. The memory range specified under the Xen compatible
- * hypervisor node on device tree can be used as target gpfn for the
- * mapping.
- *
- * - Xenstore is initialized by using the two hvm_params
- * HVM_PARAM_STORE_PFN and HVM_PARAM_STORE_EVTCHN. They can be read
- * with the HYPERVISOR_hvm_op sub-op HVMOP_get_param.
- *
- * - The paravirtualized console is initialized by using the two
- * hvm_params HVM_PARAM_CONSOLE_PFN and HVM_PARAM_CONSOLE_EVTCHN. They
- * can be read with the HYPERVISOR_hvm_op sub-op HVMOP_get_param.
- *
- * - Event channel notifications are delivered using the percpu GIC
- * interrupt specified under the Xen compatible hypervisor node on
- * device tree.
- *
- * - The device tree Xen compatible node is fully described under Linux
- * at Documentation/devicetree/bindings/arm/xen.txt.
- */
-
-#define XEN_HYPERCALL_TAG 0XEA1
-
-#define uint64_aligned_t uint64_t __attribute__((aligned(8)))
-
-#ifndef __ASSEMBLY__
-#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
- typedef union { type *p; unsigned long q; } \
- __guest_handle_ ## name; \
- typedef union { type *p; uint64_aligned_t q; } \
- __guest_handle_64_ ## name;
-
-/*
- * XEN_GUEST_HANDLE represents a guest pointer, when passed as a field
- * in a struct in memory. On ARM is always 8 bytes sizes and 8 bytes
- * aligned.
- * XEN_GUEST_HANDLE_PARAM represents a guest pointer, when passed as an
- * hypercall argument. It is 4 bytes on aarch32 and 8 bytes on aarch64.
- */
-#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
- ___DEFINE_XEN_GUEST_HANDLE(name, type); \
- ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
-#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
-#define __XEN_GUEST_HANDLE(name) __guest_handle_64_ ## name
-#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name)
-#define XEN_GUEST_HANDLE_PARAM(name) __guest_handle_ ## name
-#define set_xen_guest_handle_raw(hnd, val) \
- do { \
- typeof(&(hnd)) _sxghr_tmp = &(hnd); \
- _sxghr_tmp->q = 0; \
- _sxghr_tmp->p = val; \
- } while ( 0 )
-#ifdef __XEN_TOOLS__
-#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0)
-#endif
-#define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val)
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-/* Anonymous union includes both 32- and 64-bit names (e.g., r0/x0). */
-# define __DECL_REG(n64, n32) union { \
- uint64_t n64; \
- uint32_t n32; \
- }
-#else
-/* Non-gcc sources must always use the proper 64-bit name (e.g., x0). */
-#define __DECL_REG(n64, n32) uint64_t n64
-#endif
-
-struct vcpu_guest_core_regs
-{
- /* Aarch64 Aarch32 */
- __DECL_REG(x0, r0_usr);
- __DECL_REG(x1, r1_usr);
- __DECL_REG(x2, r2_usr);
- __DECL_REG(x3, r3_usr);
- __DECL_REG(x4, r4_usr);
- __DECL_REG(x5, r5_usr);
- __DECL_REG(x6, r6_usr);
- __DECL_REG(x7, r7_usr);
- __DECL_REG(x8, r8_usr);
- __DECL_REG(x9, r9_usr);
- __DECL_REG(x10, r10_usr);
- __DECL_REG(x11, r11_usr);
- __DECL_REG(x12, r12_usr);
-
- __DECL_REG(x13, sp_usr);
- __DECL_REG(x14, lr_usr);
-
- __DECL_REG(x15, __unused_sp_hyp);
-
- __DECL_REG(x16, lr_irq);
- __DECL_REG(x17, sp_irq);
-
- __DECL_REG(x18, lr_svc);
- __DECL_REG(x19, sp_svc);
-
- __DECL_REG(x20, lr_abt);
- __DECL_REG(x21, sp_abt);
-
- __DECL_REG(x22, lr_und);
- __DECL_REG(x23, sp_und);
-
- __DECL_REG(x24, r8_fiq);
- __DECL_REG(x25, r9_fiq);
- __DECL_REG(x26, r10_fiq);
- __DECL_REG(x27, r11_fiq);
- __DECL_REG(x28, r12_fiq);
-
- __DECL_REG(x29, sp_fiq);
- __DECL_REG(x30, lr_fiq);
-
- /* Return address and mode */
- __DECL_REG(pc64, pc32); /* ELR_EL2 */
- uint32_t cpsr; /* SPSR_EL2 */
-
- union {
- uint32_t spsr_el1; /* AArch64 */
- uint32_t spsr_svc; /* AArch32 */
- };
-
- /* AArch32 guests only */
- uint32_t spsr_fiq, spsr_irq, spsr_und, spsr_abt;
-
- /* AArch64 guests only */
- uint64_t sp_el0;
- uint64_t sp_el1, elr_el1;
-};
-typedef struct vcpu_guest_core_regs vcpu_guest_core_regs_t;
-DEFINE_XEN_GUEST_HANDLE(vcpu_guest_core_regs_t);
-
-#undef __DECL_REG
-
-typedef uint64_t xen_pfn_t;
-#define PRI_xen_pfn PRIx64
-
-/* Maximum number of virtual CPUs in legacy multi-processor guests. */
-/* Only one. All other VCPUS must use VCPUOP_register_vcpu_info */
-#define XEN_LEGACY_MAX_VCPUS 1
-
-typedef uint64_t xen_ulong_t;
-#define PRI_xen_ulong PRIx64
-
-#if defined(__XEN__) || defined(__XEN_TOOLS__)
-struct vcpu_guest_context {
-#define _VGCF_online 0
-#define VGCF_online (1<<_VGCF_online)
- uint32_t flags; /* VGCF_* */
-
- struct vcpu_guest_core_regs user_regs; /* Core CPU registers */
-
- uint32_t sctlr;
- uint64_t ttbcr, ttbr0, ttbr1;
-};
-typedef struct vcpu_guest_context vcpu_guest_context_t;
-DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
-#endif
-
-struct arch_vcpu_info {
-};
-typedef struct arch_vcpu_info arch_vcpu_info_t;
-
-struct arch_shared_info {
-};
-typedef struct arch_shared_info arch_shared_info_t;
-typedef uint64_t xen_callback_t;
-
-#endif
-
-#if defined(__XEN__) || defined(__XEN_TOOLS__)
-
-/* PSR bits (CPSR, SPSR) */
-
-#define PSR_THUMB (1<<5) /* Thumb Mode enable */
-#define PSR_FIQ_MASK (1<<6) /* Fast Interrupt mask */
-#define PSR_IRQ_MASK (1<<7) /* Interrupt mask */
-#define PSR_ABT_MASK (1<<8) /* Asynchronous Abort mask */
-#define PSR_BIG_ENDIAN (1<<9) /* arm32: Big Endian Mode */
-#define PSR_DBG_MASK (1<<9) /* arm64: Debug Exception mask */
-#define PSR_IT_MASK (0x0600fc00) /* Thumb If-Then Mask */
-#define PSR_JAZELLE (1<<24) /* Jazelle Mode */
-
-/* 32 bit modes */
-#define PSR_MODE_USR 0x10
-#define PSR_MODE_FIQ 0x11
-#define PSR_MODE_IRQ 0x12
-#define PSR_MODE_SVC 0x13
-#define PSR_MODE_MON 0x16
-#define PSR_MODE_ABT 0x17
-#define PSR_MODE_HYP 0x1a
-#define PSR_MODE_UND 0x1b
-#define PSR_MODE_SYS 0x1f
-
-/* 64 bit modes */
-#define PSR_MODE_BIT 0x10 /* Set iff AArch32 */
-#define PSR_MODE_EL3h 0x0d
-#define PSR_MODE_EL3t 0x0c
-#define PSR_MODE_EL2h 0x09
-#define PSR_MODE_EL2t 0x08
-#define PSR_MODE_EL1h 0x05
-#define PSR_MODE_EL1t 0x04
-#define PSR_MODE_EL0t 0x00
-
-#define PSR_GUEST32_INIT (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_SVC)
-#define PSR_GUEST64_INIT (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_EL1h)
-
-#define SCTLR_GUEST_INIT 0x00c50078
-
-/*
- * Virtual machine platform (memory layout, interrupts)
- *
- * These are defined for consistency between the tools and the
- * hypervisor. Guests must not rely on these hardcoded values but
- * should instead use the FDT.
- */
-
-/* Physical Address Space */
-
-/*
- * vGIC mappings: Only one set of mapping is used by the guest.
- * Therefore they can overlap.
- */
-
-/* vGIC v2 mappings */
-#define GUEST_GICD_BASE 0x03001000ULL
-#define GUEST_GICD_SIZE 0x00001000ULL
-#define GUEST_GICC_BASE 0x03002000ULL
-#define GUEST_GICC_SIZE 0x00000100ULL
-
-/* vGIC v3 mappings */
-#define GUEST_GICV3_GICD_BASE 0x03001000ULL
-#define GUEST_GICV3_GICD_SIZE 0x00010000ULL
-
-#define GUEST_GICV3_RDIST_STRIDE 0x20000ULL
-#define GUEST_GICV3_RDIST_REGIONS 1
-
-#define GUEST_GICV3_GICR0_BASE 0x03020000ULL /* vCPU0 - vCPU7 */
-#define GUEST_GICV3_GICR0_SIZE 0x00100000ULL
-
-/*
- * 16MB == 4096 pages reserved for guest to use as a region to map its
- * grant table in.
- */
-#define GUEST_GNTTAB_BASE 0x38000000ULL
-#define GUEST_GNTTAB_SIZE 0x01000000ULL
-
-#define GUEST_MAGIC_BASE 0x39000000ULL
-#define GUEST_MAGIC_SIZE 0x01000000ULL
-
-#define GUEST_RAM_BANKS 2
-
-#define GUEST_RAM0_BASE 0x40000000ULL /* 3GB of low RAM @ 1GB */
-#define GUEST_RAM0_SIZE 0xc0000000ULL
-
-#define GUEST_RAM1_BASE 0x0200000000ULL /* 1016GB of RAM @ 8GB */
-#define GUEST_RAM1_SIZE 0xfe00000000ULL
-
-#define GUEST_RAM_BASE GUEST_RAM0_BASE /* Lowest RAM address */
-/* Largest amount of actual RAM, not including holes */
-#define GUEST_RAM_MAX (GUEST_RAM0_SIZE + GUEST_RAM1_SIZE)
-/* Suitable for e.g. const uint64_t ramfoo[] = GUEST_RAM_BANK_FOOS; */
-#define GUEST_RAM_BANK_BASES { GUEST_RAM0_BASE, GUEST_RAM1_BASE }
-#define GUEST_RAM_BANK_SIZES { GUEST_RAM0_SIZE, GUEST_RAM1_SIZE }
-
-/* Interrupts */
-#define GUEST_TIMER_VIRT_PPI 27
-#define GUEST_TIMER_PHYS_S_PPI 29
-#define GUEST_TIMER_PHYS_NS_PPI 30
-#define GUEST_EVTCHN_PPI 31
-
-/* PSCI functions */
-#define PSCI_cpu_suspend 0
-#define PSCI_cpu_off 1
-#define PSCI_cpu_on 2
-#define PSCI_migrate 3
-
-#endif
-
-#endif /* __XEN_PUBLIC_ARCH_ARM_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/*
- * Structure definitions for HVM state that is held by Xen and must
- * be saved along with the domain's memory and device-model state.
- *
- * Copyright (c) 2012 Citrix Systems Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __XEN_PUBLIC_HVM_SAVE_ARM_H__
-#define __XEN_PUBLIC_HVM_SAVE_ARM_H__
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * arch-x86/cpuid.h
- *
- * CPUID interface to Xen.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2007 Citrix Systems, Inc.
- *
- * Authors:
- * Keir Fraser <keir@xen.org>
- */
-
-#ifndef __XEN_PUBLIC_ARCH_X86_CPUID_H__
-#define __XEN_PUBLIC_ARCH_X86_CPUID_H__
-
-/*
- * For compatibility with other hypervisor interfaces, the Xen cpuid leaves
- * can be found at the first otherwise unused 0x100 aligned boundary starting
- * from 0x40000000.
- *
- * e.g If viridian extensions are enabled for an HVM domain, the Xen cpuid
- * leaves will start at 0x40000100
- */
-
-#define XEN_CPUID_FIRST_LEAF 0x40000000
-#define XEN_CPUID_LEAF(i) (XEN_CPUID_FIRST_LEAF + (i))
-
-/*
- * Leaf 1 (0x40000x00)
- * EAX: Largest Xen-information leaf. All leaves up to an including @EAX
- * are supported by the Xen host.
- * EBX-EDX: "XenVMMXenVMM" signature, allowing positive identification
- * of a Xen host.
- */
-#define XEN_CPUID_SIGNATURE_EBX 0x566e6558 /* "XenV" */
-#define XEN_CPUID_SIGNATURE_ECX 0x65584d4d /* "MMXe" */
-#define XEN_CPUID_SIGNATURE_EDX 0x4d4d566e /* "nVMM" */
-
-/*
- * Leaf 2 (0x40000x01)
- * EAX[31:16]: Xen major version.
- * EAX[15: 0]: Xen minor version.
- * EBX-EDX: Reserved (currently all zeroes).
- */
-
-/*
- * Leaf 3 (0x40000x02)
- * EAX: Number of hypercall transfer pages. This register is always guaranteed
- * to specify one hypercall page.
- * EBX: Base address of Xen-specific MSRs.
- * ECX: Features 1. Unused bits are set to zero.
- * EDX: Features 2. Unused bits are set to zero.
- */
-
-/* Does the host support MMU_PT_UPDATE_PRESERVE_AD for this guest? */
-#define _XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD 0
-#define XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD (1u<<0)
-
-/*
- * Leaf 5 (0x40000x04)
- * HVM-specific features
- * EAX: Features
- * EBX: vcpu id (iff EAX has XEN_HVM_CPUID_VCPU_ID_PRESENT flag)
- */
-#define XEN_HVM_CPUID_APIC_ACCESS_VIRT (1u << 0) /* Virtualized APIC registers */
-#define XEN_HVM_CPUID_X2APIC_VIRT (1u << 1) /* Virtualized x2APIC accesses */
-/* Memory mapped from other domains has valid IOMMU entries */
-#define XEN_HVM_CPUID_IOMMU_MAPPINGS (1u << 2)
-#define XEN_HVM_CPUID_VCPU_ID_PRESENT (1u << 3) /* vcpu id is present in EBX */
-
-#define XEN_CPUID_MAX_NUM_LEAVES 4
-
-#endif /* __XEN_PUBLIC_ARCH_X86_CPUID_H__ */
+++ /dev/null
-/*
- * Structure definitions for HVM state that is held by Xen and must
- * be saved along with the domain's memory and device-model state.
- *
- * Copyright (c) 2007 XenSource Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __XEN_PUBLIC_HVM_SAVE_X86_H__
-#define __XEN_PUBLIC_HVM_SAVE_X86_H__
-
-/*
- * Save/restore header: general info about the save file.
- */
-
-#define HVM_FILE_MAGIC 0x54381286
-#define HVM_FILE_VERSION 0x00000001
-
-struct hvm_save_header {
- uint32_t magic; /* Must be HVM_FILE_MAGIC */
- uint32_t version; /* File format version */
- uint64_t changeset; /* Version of Xen that saved this file */
- uint32_t cpuid; /* CPUID[0x01][%eax] on the saving machine */
- uint32_t gtsc_khz; /* Guest's TSC frequency in kHz */
-};
-
-DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header);
-
-
-/*
- * Processor
- *
- * Compat: Pre-3.4 didn't have msr_tsc_aux
- */
-
-struct hvm_hw_cpu {
- uint8_t fpu_regs[512];
-
- uint64_t rax;
- uint64_t rbx;
- uint64_t rcx;
- uint64_t rdx;
- uint64_t rbp;
- uint64_t rsi;
- uint64_t rdi;
- uint64_t rsp;
- uint64_t r8;
- uint64_t r9;
- uint64_t r10;
- uint64_t r11;
- uint64_t r12;
- uint64_t r13;
- uint64_t r14;
- uint64_t r15;
-
- uint64_t rip;
- uint64_t rflags;
-
- uint64_t cr0;
- uint64_t cr2;
- uint64_t cr3;
- uint64_t cr4;
-
- uint64_t dr0;
- uint64_t dr1;
- uint64_t dr2;
- uint64_t dr3;
- uint64_t dr6;
- uint64_t dr7;
-
- uint32_t cs_sel;
- uint32_t ds_sel;
- uint32_t es_sel;
- uint32_t fs_sel;
- uint32_t gs_sel;
- uint32_t ss_sel;
- uint32_t tr_sel;
- uint32_t ldtr_sel;
-
- uint32_t cs_limit;
- uint32_t ds_limit;
- uint32_t es_limit;
- uint32_t fs_limit;
- uint32_t gs_limit;
- uint32_t ss_limit;
- uint32_t tr_limit;
- uint32_t ldtr_limit;
- uint32_t idtr_limit;
- uint32_t gdtr_limit;
-
- uint64_t cs_base;
- uint64_t ds_base;
- uint64_t es_base;
- uint64_t fs_base;
- uint64_t gs_base;
- uint64_t ss_base;
- uint64_t tr_base;
- uint64_t ldtr_base;
- uint64_t idtr_base;
- uint64_t gdtr_base;
-
- uint32_t cs_arbytes;
- uint32_t ds_arbytes;
- uint32_t es_arbytes;
- uint32_t fs_arbytes;
- uint32_t gs_arbytes;
- uint32_t ss_arbytes;
- uint32_t tr_arbytes;
- uint32_t ldtr_arbytes;
-
- uint64_t sysenter_cs;
- uint64_t sysenter_esp;
- uint64_t sysenter_eip;
-
- /* msr for em64t */
- uint64_t shadow_gs;
-
- /* msr content saved/restored. */
- uint64_t msr_flags;
- uint64_t msr_lstar;
- uint64_t msr_star;
- uint64_t msr_cstar;
- uint64_t msr_syscall_mask;
- uint64_t msr_efer;
- uint64_t msr_tsc_aux;
-
- /* guest's idea of what rdtsc() would return */
- uint64_t tsc;
-
- /* pending event, if any */
- union {
- uint32_t pending_event;
- struct {
- uint8_t pending_vector:8;
- uint8_t pending_type:3;
- uint8_t pending_error_valid:1;
- uint32_t pending_reserved:19;
- uint8_t pending_valid:1;
- };
- };
- /* error code for pending event */
- uint32_t error_code;
-};
-
-struct hvm_hw_cpu_compat {
- uint8_t fpu_regs[512];
-
- uint64_t rax;
- uint64_t rbx;
- uint64_t rcx;
- uint64_t rdx;
- uint64_t rbp;
- uint64_t rsi;
- uint64_t rdi;
- uint64_t rsp;
- uint64_t r8;
- uint64_t r9;
- uint64_t r10;
- uint64_t r11;
- uint64_t r12;
- uint64_t r13;
- uint64_t r14;
- uint64_t r15;
-
- uint64_t rip;
- uint64_t rflags;
-
- uint64_t cr0;
- uint64_t cr2;
- uint64_t cr3;
- uint64_t cr4;
-
- uint64_t dr0;
- uint64_t dr1;
- uint64_t dr2;
- uint64_t dr3;
- uint64_t dr6;
- uint64_t dr7;
-
- uint32_t cs_sel;
- uint32_t ds_sel;
- uint32_t es_sel;
- uint32_t fs_sel;
- uint32_t gs_sel;
- uint32_t ss_sel;
- uint32_t tr_sel;
- uint32_t ldtr_sel;
-
- uint32_t cs_limit;
- uint32_t ds_limit;
- uint32_t es_limit;
- uint32_t fs_limit;
- uint32_t gs_limit;
- uint32_t ss_limit;
- uint32_t tr_limit;
- uint32_t ldtr_limit;
- uint32_t idtr_limit;
- uint32_t gdtr_limit;
-
- uint64_t cs_base;
- uint64_t ds_base;
- uint64_t es_base;
- uint64_t fs_base;
- uint64_t gs_base;
- uint64_t ss_base;
- uint64_t tr_base;
- uint64_t ldtr_base;
- uint64_t idtr_base;
- uint64_t gdtr_base;
-
- uint32_t cs_arbytes;
- uint32_t ds_arbytes;
- uint32_t es_arbytes;
- uint32_t fs_arbytes;
- uint32_t gs_arbytes;
- uint32_t ss_arbytes;
- uint32_t tr_arbytes;
- uint32_t ldtr_arbytes;
-
- uint64_t sysenter_cs;
- uint64_t sysenter_esp;
- uint64_t sysenter_eip;
-
- /* msr for em64t */
- uint64_t shadow_gs;
-
- /* msr content saved/restored. */
- uint64_t msr_flags;
- uint64_t msr_lstar;
- uint64_t msr_star;
- uint64_t msr_cstar;
- uint64_t msr_syscall_mask;
- uint64_t msr_efer;
- /*uint64_t msr_tsc_aux; COMPAT */
-
- /* guest's idea of what rdtsc() would return */
- uint64_t tsc;
-
- /* pending event, if any */
- union {
- uint32_t pending_event;
- struct {
- uint8_t pending_vector:8;
- uint8_t pending_type:3;
- uint8_t pending_error_valid:1;
- uint32_t pending_reserved:19;
- uint8_t pending_valid:1;
- };
- };
- /* error code for pending event */
- uint32_t error_code;
-};
-
-static inline int _hvm_hw_fix_cpu(void *h) {
-
- union hvm_hw_cpu_union {
- struct hvm_hw_cpu nat;
- struct hvm_hw_cpu_compat cmp;
- } *ucpu = (union hvm_hw_cpu_union *)h;
-
- /* If we copy from the end backwards, we should
- * be able to do the modification in-place */
- ucpu->nat.error_code = ucpu->cmp.error_code;
- ucpu->nat.pending_event = ucpu->cmp.pending_event;
- ucpu->nat.tsc = ucpu->cmp.tsc;
- ucpu->nat.msr_tsc_aux = 0;
-
- return 0;
-}
-
-DECLARE_HVM_SAVE_TYPE_COMPAT(CPU, 2, struct hvm_hw_cpu, \
- struct hvm_hw_cpu_compat, _hvm_hw_fix_cpu);
-
-/*
- * PIC
- */
-
-struct hvm_hw_vpic {
- /* IR line bitmasks. */
- uint8_t irr;
- uint8_t imr;
- uint8_t isr;
-
- /* Line IRx maps to IRQ irq_base+x */
- uint8_t irq_base;
-
- /*
- * Where are we in ICW2-4 initialisation (0 means no init in progress)?
- * Bits 0-1 (=x): Next write at A=1 sets ICW(x+1).
- * Bit 2: ICW1.IC4 (1 == ICW4 included in init sequence)
- * Bit 3: ICW1.SNGL (0 == ICW3 included in init sequence)
- */
- uint8_t init_state:4;
-
- /* IR line with highest priority. */
- uint8_t priority_add:4;
-
- /* Reads from A=0 obtain ISR or IRR? */
- uint8_t readsel_isr:1;
-
- /* Reads perform a polling read? */
- uint8_t poll:1;
-
- /* Automatically clear IRQs from the ISR during INTA? */
- uint8_t auto_eoi:1;
-
- /* Automatically rotate IRQ priorities during AEOI? */
- uint8_t rotate_on_auto_eoi:1;
-
- /* Exclude slave inputs when considering in-service IRQs? */
- uint8_t special_fully_nested_mode:1;
-
- /* Special mask mode excludes masked IRs from AEOI and priority checks. */
- uint8_t special_mask_mode:1;
-
- /* Is this a master PIC or slave PIC? (NB. This is not programmable.) */
- uint8_t is_master:1;
-
- /* Edge/trigger selection. */
- uint8_t elcr;
-
- /* Virtual INT output. */
- uint8_t int_output;
-};
-
-DECLARE_HVM_SAVE_TYPE(PIC, 3, struct hvm_hw_vpic);
-
-
-/*
- * IO-APIC
- */
-
-#define VIOAPIC_NUM_PINS 48 /* 16 ISA IRQs, 32 non-legacy PCI IRQS. */
-
-struct hvm_hw_vioapic {
- uint64_t base_address;
- uint32_t ioregsel;
- uint32_t id;
- union vioapic_redir_entry
- {
- uint64_t bits;
- struct {
- uint8_t vector;
- uint8_t delivery_mode:3;
- uint8_t dest_mode:1;
- uint8_t delivery_status:1;
- uint8_t polarity:1;
- uint8_t remote_irr:1;
- uint8_t trig_mode:1;
- uint8_t mask:1;
- uint8_t reserve:7;
- uint8_t reserved[4];
- uint8_t dest_id;
- } fields;
- } redirtbl[VIOAPIC_NUM_PINS];
-};
-
-DECLARE_HVM_SAVE_TYPE(IOAPIC, 4, struct hvm_hw_vioapic);
-
-
-/*
- * LAPIC
- */
-
-struct hvm_hw_lapic {
- uint64_t apic_base_msr;
- uint32_t disabled; /* VLAPIC_xx_DISABLED */
- uint32_t timer_divisor;
- uint64_t tdt_msr;
-};
-
-DECLARE_HVM_SAVE_TYPE(LAPIC, 5, struct hvm_hw_lapic);
-
-struct hvm_hw_lapic_regs {
- uint8_t data[1024];
-};
-
-DECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 6, struct hvm_hw_lapic_regs);
-
-
-/*
- * IRQs
- */
-
-struct hvm_hw_pci_irqs {
- /*
- * Virtual interrupt wires for a single PCI bus.
- * Indexed by: device*4 + INTx#.
- */
- union {
- unsigned long i[16 / sizeof (unsigned long)]; /* DECLARE_BITMAP(i, 32*4); */
- uint64_t pad[2];
- };
-};
-
-DECLARE_HVM_SAVE_TYPE(PCI_IRQ, 7, struct hvm_hw_pci_irqs);
-
-struct hvm_hw_isa_irqs {
- /*
- * Virtual interrupt wires for ISA devices.
- * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
- */
- union {
- unsigned long i[1]; /* DECLARE_BITMAP(i, 16); */
- uint64_t pad[1];
- };
-};
-
-DECLARE_HVM_SAVE_TYPE(ISA_IRQ, 8, struct hvm_hw_isa_irqs);
-
-struct hvm_hw_pci_link {
- /*
- * PCI-ISA interrupt router.
- * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
- * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
- * The router provides a programmable mapping from each link to a GSI.
- */
- uint8_t route[4];
- uint8_t pad0[4];
-};
-
-DECLARE_HVM_SAVE_TYPE(PCI_LINK, 9, struct hvm_hw_pci_link);
-
-/*
- * PIT
- */
-
-struct hvm_hw_pit {
- struct hvm_hw_pit_channel {
- uint32_t count; /* can be 65536 */
- uint16_t latched_count;
- uint8_t count_latched;
- uint8_t status_latched;
- uint8_t status;
- uint8_t read_state;
- uint8_t write_state;
- uint8_t write_latch;
- uint8_t rw_mode;
- uint8_t mode;
- uint8_t bcd; /* not supported */
- uint8_t gate; /* timer start */
- } channels[3]; /* 3 x 16 bytes */
- uint32_t speaker_data_on;
- uint32_t pad0;
-};
-
-DECLARE_HVM_SAVE_TYPE(PIT, 10, struct hvm_hw_pit);
-
-
-/*
- * RTC
- */
-
-#define RTC_CMOS_SIZE 14
-struct hvm_hw_rtc {
- /* CMOS bytes */
- uint8_t cmos_data[RTC_CMOS_SIZE];
- /* Index register for 2-part operations */
- uint8_t cmos_index;
- uint8_t pad0;
-};
-
-DECLARE_HVM_SAVE_TYPE(RTC, 11, struct hvm_hw_rtc);
-
-
-/*
- * HPET
- */
-
-#define HPET_TIMER_NUM 3 /* 3 timers supported now */
-struct hvm_hw_hpet {
- /* Memory-mapped, software visible registers */
- uint64_t capability; /* capabilities */
- uint64_t res0; /* reserved */
- uint64_t config; /* configuration */
- uint64_t res1; /* reserved */
- uint64_t isr; /* interrupt status reg */
- uint64_t res2[25]; /* reserved */
- uint64_t mc64; /* main counter */
- uint64_t res3; /* reserved */
- struct { /* timers */
- uint64_t config; /* configuration/cap */
- uint64_t cmp; /* comparator */
- uint64_t fsb; /* FSB route, not supported now */
- uint64_t res4; /* reserved */
- } timers[HPET_TIMER_NUM];
- uint64_t res5[4*(24-HPET_TIMER_NUM)]; /* reserved, up to 0x3ff */
-
- /* Hidden register state */
- uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */
-};
-
-DECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet);
-
-
-/*
- * PM timer
- */
-
-struct hvm_hw_pmtimer {
- uint32_t tmr_val; /* PM_TMR_BLK.TMR_VAL: 32bit free-running counter */
- uint16_t pm1a_sts; /* PM1a_EVT_BLK.PM1a_STS: status register */
- uint16_t pm1a_en; /* PM1a_EVT_BLK.PM1a_EN: enable register */
-};
-
-DECLARE_HVM_SAVE_TYPE(PMTIMER, 13, struct hvm_hw_pmtimer);
-
-/*
- * MTRR MSRs
- */
-
-struct hvm_hw_mtrr {
-#define MTRR_VCNT 8
-#define NUM_FIXED_MSR 11
- uint64_t msr_pat_cr;
- /* mtrr physbase & physmask msr pair*/
- uint64_t msr_mtrr_var[MTRR_VCNT*2];
- uint64_t msr_mtrr_fixed[NUM_FIXED_MSR];
- uint64_t msr_mtrr_cap;
- uint64_t msr_mtrr_def_type;
-};
-
-DECLARE_HVM_SAVE_TYPE(MTRR, 14, struct hvm_hw_mtrr);
-
-/*
- * The save area of XSAVE/XRSTOR.
- */
-
-struct hvm_hw_cpu_xsave {
- uint64_t xfeature_mask; /* Ignored */
- uint64_t xcr0; /* Updated by XSETBV */
- uint64_t xcr0_accum; /* Updated by XSETBV */
- struct {
- struct { char x[512]; } fpu_sse;
-
- struct {
- uint64_t xstate_bv; /* Updated by XRSTOR */
- uint64_t reserved[7];
- } xsave_hdr; /* The 64-byte header */
-
- struct { char x[0]; } ymm; /* YMM */
- } save_area;
-};
-
-#define CPU_XSAVE_CODE 16
-
-/*
- * Viridian hypervisor context.
- */
-
-struct hvm_viridian_domain_context {
- uint64_t hypercall_gpa;
- uint64_t guest_os_id;
- uint64_t time_ref_count;
- uint64_t reference_tsc;
-};
-
-DECLARE_HVM_SAVE_TYPE(VIRIDIAN_DOMAIN, 15, struct hvm_viridian_domain_context);
-
-struct hvm_viridian_vcpu_context {
- uint64_t apic_assist;
-};
-
-DECLARE_HVM_SAVE_TYPE(VIRIDIAN_VCPU, 17, struct hvm_viridian_vcpu_context);
-
-struct hvm_vmce_vcpu {
- uint64_t caps;
- uint64_t mci_ctl2_bank0;
- uint64_t mci_ctl2_bank1;
-};
-
-DECLARE_HVM_SAVE_TYPE(VMCE_VCPU, 18, struct hvm_vmce_vcpu);
-
-struct hvm_tsc_adjust {
- uint64_t tsc_adjust;
-};
-
-DECLARE_HVM_SAVE_TYPE(TSC_ADJUST, 19, struct hvm_tsc_adjust);
-
-
-struct hvm_msr {
- uint32_t count;
- struct hvm_one_msr {
- uint32_t index;
- uint32_t _rsvd;
- uint64_t val;
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
- } msr[];
-#elif defined(__GNUC__)
- } msr[0];
-#else
- } msr[1 /* variable size */];
-#endif
-};
-
-#define CPU_MSR_CODE 20
-
-/*
- * Largest type-code in use
- */
-#define HVM_SAVE_CODE_MAX 20
-
-#endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * arch-x86/mca.h
- *
- * Contributed by Advanced Micro Devices, Inc.
- * Author: Christoph Egger <Christoph.Egger@amd.com>
- *
- * Guest OS machine check interface to x86 Xen.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/* Full MCA functionality has the following Usecases from the guest side:
- *
- * Must have's:
- * 1. Dom0 and DomU register machine check trap callback handlers
- * (already done via "set_trap_table" hypercall)
- * 2. Dom0 registers machine check event callback handler
- * (doable via EVTCHNOP_bind_virq)
- * 3. Dom0 and DomU fetches machine check data
- * 4. Dom0 wants Xen to notify a DomU
- * 5. Dom0 gets DomU ID from physical address
- * 6. Dom0 wants Xen to kill DomU (already done for "xm destroy")
- *
- * Nice to have's:
- * 7. Dom0 wants Xen to deactivate a physical CPU
- * This is better done as separate task, physical CPU hotplugging,
- * and hypercall(s) should be sysctl's
- * 8. Page migration proposed from Xen NUMA work, where Dom0 can tell Xen to
- * move a DomU (or Dom0 itself) away from a malicious page
- * producing correctable errors.
- * 9. offlining physical page:
- * Xen free's and never re-uses a certain physical page.
- * 10. Testfacility: Allow Dom0 to write values into machine check MSR's
- * and tell Xen to trigger a machine check
- */
-
-#ifndef __XEN_PUBLIC_ARCH_X86_MCA_H__
-#define __XEN_PUBLIC_ARCH_X86_MCA_H__
-
-/* Hypercall */
-#define __HYPERVISOR_mca __HYPERVISOR_arch_0
-
-/*
- * The xen-unstable repo has interface version 0x03000001; out interface
- * is incompatible with that and any future minor revisions, so we
- * choose a different version number range that is numerically less
- * than that used in xen-unstable.
- */
-#define XEN_MCA_INTERFACE_VERSION 0x01ecc003
-
-/* IN: Dom0 calls hypercall to retrieve nonurgent telemetry */
-#define XEN_MC_NONURGENT 0x0001
-/* IN: Dom0/DomU calls hypercall to retrieve urgent telemetry */
-#define XEN_MC_URGENT 0x0002
-/* IN: Dom0 acknowledges previosly-fetched telemetry */
-#define XEN_MC_ACK 0x0004
-
-/* OUT: All is ok */
-#define XEN_MC_OK 0x0
-/* OUT: Domain could not fetch data. */
-#define XEN_MC_FETCHFAILED 0x1
-/* OUT: There was no machine check data to fetch. */
-#define XEN_MC_NODATA 0x2
-/* OUT: Between notification time and this hypercall an other
- * (most likely) correctable error happened. The fetched data,
- * does not match the original machine check data. */
-#define XEN_MC_NOMATCH 0x4
-
-/* OUT: DomU did not register MC NMI handler. Try something else. */
-#define XEN_MC_CANNOTHANDLE 0x8
-/* OUT: Notifying DomU failed. Retry later or try something else. */
-#define XEN_MC_NOTDELIVERED 0x10
-/* Note, XEN_MC_CANNOTHANDLE and XEN_MC_NOTDELIVERED are mutually exclusive. */
-
-
-#ifndef __ASSEMBLY__
-
-#define VIRQ_MCA VIRQ_ARCH_0 /* G. (DOM0) Machine Check Architecture */
-
-/*
- * Machine Check Architecure:
- * structs are read-only and used to report all kinds of
- * correctable and uncorrectable errors detected by the HW.
- * Dom0 and DomU: register a handler to get notified.
- * Dom0 only: Correctable errors are reported via VIRQ_MCA
- * Dom0 and DomU: Uncorrectable errors are reported via nmi handlers
- */
-#define MC_TYPE_GLOBAL 0
-#define MC_TYPE_BANK 1
-#define MC_TYPE_EXTENDED 2
-#define MC_TYPE_RECOVERY 3
-
-struct mcinfo_common {
- uint16_t type; /* structure type */
- uint16_t size; /* size of this struct in bytes */
-};
-
-
-#define MC_FLAG_CORRECTABLE (1 << 0)
-#define MC_FLAG_UNCORRECTABLE (1 << 1)
-#define MC_FLAG_RECOVERABLE (1 << 2)
-#define MC_FLAG_POLLED (1 << 3)
-#define MC_FLAG_RESET (1 << 4)
-#define MC_FLAG_CMCI (1 << 5)
-#define MC_FLAG_MCE (1 << 6)
-/* contains global x86 mc information */
-struct mcinfo_global {
- struct mcinfo_common common;
-
- /* running domain at the time in error (most likely the impacted one) */
- uint16_t mc_domid;
- uint16_t mc_vcpuid; /* virtual cpu scheduled for mc_domid */
- uint32_t mc_socketid; /* physical socket of the physical core */
- uint16_t mc_coreid; /* physical impacted core */
- uint16_t mc_core_threadid; /* core thread of physical core */
- uint32_t mc_apicid;
- uint32_t mc_flags;
- uint64_t mc_gstatus; /* global status */
-};
-
-/* contains bank local x86 mc information */
-struct mcinfo_bank {
- struct mcinfo_common common;
-
- uint16_t mc_bank; /* bank nr */
- uint16_t mc_domid; /* Usecase 5: domain referenced by mc_addr on dom0
- * and if mc_addr is valid. Never valid on DomU. */
- uint64_t mc_status; /* bank status */
- uint64_t mc_addr; /* bank address, only valid
- * if addr bit is set in mc_status */
- uint64_t mc_misc;
- uint64_t mc_ctrl2;
- uint64_t mc_tsc;
-};
-
-
-struct mcinfo_msr {
- uint64_t reg; /* MSR */
- uint64_t value; /* MSR value */
-};
-
-/* contains mc information from other
- * or additional mc MSRs */
-struct mcinfo_extended {
- struct mcinfo_common common;
-
- /* You can fill up to five registers.
- * If you need more, then use this structure
- * multiple times. */
-
- uint32_t mc_msrs; /* Number of msr with valid values. */
- /*
- * Currently Intel extended MSR (32/64) include all gp registers
- * and E(R)FLAGS, E(R)IP, E(R)MISC, up to 11/19 of them might be
- * useful at present. So expand this array to 16/32 to leave room.
- */
- struct mcinfo_msr mc_msr[sizeof(void *) * 4];
-};
-
-/* Recovery Action flags. Giving recovery result information to DOM0 */
-
-/* Xen takes successful recovery action, the error is recovered */
-#define REC_ACTION_RECOVERED (0x1 << 0)
-/* No action is performed by XEN */
-#define REC_ACTION_NONE (0x1 << 1)
-/* It's possible DOM0 might take action ownership in some case */
-#define REC_ACTION_NEED_RESET (0x1 << 2)
-
-/* Different Recovery Action types, if the action is performed successfully,
- * REC_ACTION_RECOVERED flag will be returned.
- */
-
-/* Page Offline Action */
-#define MC_ACTION_PAGE_OFFLINE (0x1 << 0)
-/* CPU offline Action */
-#define MC_ACTION_CPU_OFFLINE (0x1 << 1)
-/* L3 cache disable Action */
-#define MC_ACTION_CACHE_SHRINK (0x1 << 2)
-
-/* Below interface used between XEN/DOM0 for passing XEN's recovery action
- * information to DOM0.
- * usage Senario: After offlining broken page, XEN might pass its page offline
- * recovery action result to DOM0. DOM0 will save the information in
- * non-volatile memory for further proactive actions, such as offlining the
- * easy broken page earlier when doing next reboot.
-*/
-struct page_offline_action
-{
- /* Params for passing the offlined page number to DOM0 */
- uint64_t mfn;
- uint64_t status;
-};
-
-struct cpu_offline_action
-{
- /* Params for passing the identity of the offlined CPU to DOM0 */
- uint32_t mc_socketid;
- uint16_t mc_coreid;
- uint16_t mc_core_threadid;
-};
-
-#define MAX_UNION_SIZE 16
-struct mcinfo_recovery
-{
- struct mcinfo_common common;
- uint16_t mc_bank; /* bank nr */
- uint8_t action_flags;
- uint8_t action_types;
- union {
- struct page_offline_action page_retire;
- struct cpu_offline_action cpu_offline;
- uint8_t pad[MAX_UNION_SIZE];
- } action_info;
-};
-
-
-#define MCINFO_HYPERCALLSIZE 1024
-#define MCINFO_MAXSIZE 768
-
-#define MCINFO_FLAGS_UNCOMPLETE 0x1
-struct mc_info {
- /* Number of mcinfo_* entries in mi_data */
- uint32_t mi_nentries;
- uint32_t flags;
- uint64_t mi_data[(MCINFO_MAXSIZE - 1) / 8];
-};
-typedef struct mc_info mc_info_t;
-DEFINE_XEN_GUEST_HANDLE(mc_info_t);
-
-#define __MC_MSR_ARRAYSIZE 8
-#define __MC_NMSRS 1
-#define MC_NCAPS 7 /* 7 CPU feature flag words */
-#define MC_CAPS_STD_EDX 0 /* cpuid level 0x00000001 (%edx) */
-#define MC_CAPS_AMD_EDX 1 /* cpuid level 0x80000001 (%edx) */
-#define MC_CAPS_TM 2 /* cpuid level 0x80860001 (TransMeta) */
-#define MC_CAPS_LINUX 3 /* Linux-defined */
-#define MC_CAPS_STD_ECX 4 /* cpuid level 0x00000001 (%ecx) */
-#define MC_CAPS_VIA 5 /* cpuid level 0xc0000001 */
-#define MC_CAPS_AMD_ECX 6 /* cpuid level 0x80000001 (%ecx) */
-
-struct mcinfo_logical_cpu {
- uint32_t mc_cpunr;
- uint32_t mc_chipid;
- uint16_t mc_coreid;
- uint16_t mc_threadid;
- uint32_t mc_apicid;
- uint32_t mc_clusterid;
- uint32_t mc_ncores;
- uint32_t mc_ncores_active;
- uint32_t mc_nthreads;
- int32_t mc_cpuid_level;
- uint32_t mc_family;
- uint32_t mc_vendor;
- uint32_t mc_model;
- uint32_t mc_step;
- char mc_vendorid[16];
- char mc_brandid[64];
- uint32_t mc_cpu_caps[MC_NCAPS];
- uint32_t mc_cache_size;
- uint32_t mc_cache_alignment;
- int32_t mc_nmsrvals;
- struct mcinfo_msr mc_msrvalues[__MC_MSR_ARRAYSIZE];
-};
-typedef struct mcinfo_logical_cpu xen_mc_logical_cpu_t;
-DEFINE_XEN_GUEST_HANDLE(xen_mc_logical_cpu_t);
-
-
-/*
- * OS's should use these instead of writing their own lookup function
- * each with its own bugs and drawbacks.
- * We use macros instead of static inline functions to allow guests
- * to include this header in assembly files (*.S).
- */
-/* Prototype:
- * uint32_t x86_mcinfo_nentries(struct mc_info *mi);
- */
-#define x86_mcinfo_nentries(_mi) \
- (_mi)->mi_nentries
-/* Prototype:
- * struct mcinfo_common *x86_mcinfo_first(struct mc_info *mi);
- */
-#define x86_mcinfo_first(_mi) \
- ((struct mcinfo_common *)(_mi)->mi_data)
-/* Prototype:
- * struct mcinfo_common *x86_mcinfo_next(struct mcinfo_common *mic);
- */
-#define x86_mcinfo_next(_mic) \
- ((struct mcinfo_common *)((uint8_t *)(_mic) + (_mic)->size))
-
-/* Prototype:
- * void x86_mcinfo_lookup(void *ret, struct mc_info *mi, uint16_t type);
- */
-#define x86_mcinfo_lookup(_ret, _mi, _type) \
- do { \
- uint32_t found, i; \
- struct mcinfo_common *_mic; \
- \
- found = 0; \
- (_ret) = NULL; \
- if (_mi == NULL) break; \
- _mic = x86_mcinfo_first(_mi); \
- for (i = 0; i < x86_mcinfo_nentries(_mi); i++) { \
- if (_mic->type == (_type)) { \
- found = 1; \
- break; \
- } \
- _mic = x86_mcinfo_next(_mic); \
- } \
- (_ret) = found ? _mic : NULL; \
- } while (0)
-
-
-/* Usecase 1
- * Register machine check trap callback handler
- * (already done via "set_trap_table" hypercall)
- */
-
-/* Usecase 2
- * Dom0 registers machine check event callback handler
- * done by EVTCHNOP_bind_virq
- */
-
-/* Usecase 3
- * Fetch machine check data from hypervisor.
- * Note, this hypercall is special, because both Dom0 and DomU must use this.
- */
-#define XEN_MC_fetch 1
-struct xen_mc_fetch {
- /* IN/OUT variables. */
- uint32_t flags; /* IN: XEN_MC_NONURGENT, XEN_MC_URGENT,
- XEN_MC_ACK if ack'ing an earlier fetch */
- /* OUT: XEN_MC_OK, XEN_MC_FETCHFAILED,
- XEN_MC_NODATA, XEN_MC_NOMATCH */
- uint32_t _pad0;
- uint64_t fetch_id; /* OUT: id for ack, IN: id we are ack'ing */
-
- /* OUT variables. */
- XEN_GUEST_HANDLE(mc_info_t) data;
-};
-typedef struct xen_mc_fetch xen_mc_fetch_t;
-DEFINE_XEN_GUEST_HANDLE(xen_mc_fetch_t);
-
-
-/* Usecase 4
- * This tells the hypervisor to notify a DomU about the machine check error
- */
-#define XEN_MC_notifydomain 2
-struct xen_mc_notifydomain {
- /* IN variables. */
- uint16_t mc_domid; /* The unprivileged domain to notify. */
- uint16_t mc_vcpuid; /* The vcpu in mc_domid to notify.
- * Usually echo'd value from the fetch hypercall. */
-
- /* IN/OUT variables. */
- uint32_t flags;
-
-/* IN: XEN_MC_CORRECTABLE, XEN_MC_TRAP */
-/* OUT: XEN_MC_OK, XEN_MC_CANNOTHANDLE, XEN_MC_NOTDELIVERED, XEN_MC_NOMATCH */
-};
-typedef struct xen_mc_notifydomain xen_mc_notifydomain_t;
-DEFINE_XEN_GUEST_HANDLE(xen_mc_notifydomain_t);
-
-#define XEN_MC_physcpuinfo 3
-struct xen_mc_physcpuinfo {
- /* IN/OUT */
- uint32_t ncpus;
- uint32_t _pad0;
- /* OUT */
- XEN_GUEST_HANDLE(xen_mc_logical_cpu_t) info;
-};
-
-#define XEN_MC_msrinject 4
-#define MC_MSRINJ_MAXMSRS 8
-struct xen_mc_msrinject {
- /* IN */
- uint32_t mcinj_cpunr; /* target processor id */
- uint32_t mcinj_flags; /* see MC_MSRINJ_F_* below */
- uint32_t mcinj_count; /* 0 .. count-1 in array are valid */
- uint32_t _pad0;
- struct mcinfo_msr mcinj_msr[MC_MSRINJ_MAXMSRS];
-};
-
-/* Flags for mcinj_flags above; bits 16-31 are reserved */
-#define MC_MSRINJ_F_INTERPOSE 0x1
-
-#define XEN_MC_mceinject 5
-struct xen_mc_mceinject {
- unsigned int mceinj_cpunr; /* target processor id */
-};
-
-#if defined(__XEN__) || defined(__XEN_TOOLS__)
-#define XEN_MC_inject_v2 6
-#define XEN_MC_INJECT_TYPE_MASK 0x7
-#define XEN_MC_INJECT_TYPE_MCE 0x0
-#define XEN_MC_INJECT_TYPE_CMCI 0x1
-
-#define XEN_MC_INJECT_CPU_BROADCAST 0x8
-
-struct xen_mc_inject_v2 {
- uint32_t flags;
- struct xenctl_bitmap cpumap;
-};
-#endif
-
-struct xen_mc {
- uint32_t cmd;
- uint32_t interface_version; /* XEN_MCA_INTERFACE_VERSION */
- union {
- struct xen_mc_fetch mc_fetch;
- struct xen_mc_notifydomain mc_notifydomain;
- struct xen_mc_physcpuinfo mc_physcpuinfo;
- struct xen_mc_msrinject mc_msrinject;
- struct xen_mc_mceinject mc_mceinject;
-#if defined(__XEN__) || defined(__XEN_TOOLS__)
- struct xen_mc_inject_v2 mc_inject_v2;
-#endif
- } u;
-};
-typedef struct xen_mc xen_mc_t;
-DEFINE_XEN_GUEST_HANDLE(xen_mc_t);
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __XEN_PUBLIC_ARCH_X86_MCA_H__ */
+++ /dev/null
-/******************************************************************************
- * xen-x86_32.h
- *
- * Guest OS interface to x86 32-bit Xen.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2004-2007, K A Fraser
- */
-
-#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
-#define __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
-
-/*
- * Hypercall interface:
- * Input: %ebx, %ecx, %edx, %esi, %edi, %ebp (arguments 1-6)
- * Output: %eax
- * Access is via hypercall page (set up by guest loader or via a Xen MSR):
- * call hypercall_page + hypercall-number * 32
- * Clobbered: Argument registers (e.g., 2-arg hypercall clobbers %ebx,%ecx)
- */
-
-/*
- * These flat segments are in the Xen-private section of every GDT. Since these
- * are also present in the initial GDT, many OSes will be able to avoid
- * installing their own GDT.
- */
-#define FLAT_RING1_CS 0xe019 /* GDT index 259 */
-#define FLAT_RING1_DS 0xe021 /* GDT index 260 */
-#define FLAT_RING1_SS 0xe021 /* GDT index 260 */
-#define FLAT_RING3_CS 0xe02b /* GDT index 261 */
-#define FLAT_RING3_DS 0xe033 /* GDT index 262 */
-#define FLAT_RING3_SS 0xe033 /* GDT index 262 */
-
-#define FLAT_KERNEL_CS FLAT_RING1_CS
-#define FLAT_KERNEL_DS FLAT_RING1_DS
-#define FLAT_KERNEL_SS FLAT_RING1_SS
-#define FLAT_USER_CS FLAT_RING3_CS
-#define FLAT_USER_DS FLAT_RING3_DS
-#define FLAT_USER_SS FLAT_RING3_SS
-
-#define __HYPERVISOR_VIRT_START_PAE 0xF5800000
-#define __MACH2PHYS_VIRT_START_PAE 0xF5800000
-#define __MACH2PHYS_VIRT_END_PAE 0xF6800000
-#define HYPERVISOR_VIRT_START_PAE \
- mk_unsigned_long(__HYPERVISOR_VIRT_START_PAE)
-#define MACH2PHYS_VIRT_START_PAE \
- mk_unsigned_long(__MACH2PHYS_VIRT_START_PAE)
-#define MACH2PHYS_VIRT_END_PAE \
- mk_unsigned_long(__MACH2PHYS_VIRT_END_PAE)
-
-/* Non-PAE bounds are obsolete. */
-#define __HYPERVISOR_VIRT_START_NONPAE 0xFC000000
-#define __MACH2PHYS_VIRT_START_NONPAE 0xFC000000
-#define __MACH2PHYS_VIRT_END_NONPAE 0xFC400000
-#define HYPERVISOR_VIRT_START_NONPAE \
- mk_unsigned_long(__HYPERVISOR_VIRT_START_NONPAE)
-#define MACH2PHYS_VIRT_START_NONPAE \
- mk_unsigned_long(__MACH2PHYS_VIRT_START_NONPAE)
-#define MACH2PHYS_VIRT_END_NONPAE \
- mk_unsigned_long(__MACH2PHYS_VIRT_END_NONPAE)
-
-#define __HYPERVISOR_VIRT_START __HYPERVISOR_VIRT_START_PAE
-#define __MACH2PHYS_VIRT_START __MACH2PHYS_VIRT_START_PAE
-#define __MACH2PHYS_VIRT_END __MACH2PHYS_VIRT_END_PAE
-
-#ifndef HYPERVISOR_VIRT_START
-#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
-#endif
-
-#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START)
-#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END)
-#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>2)
-#ifndef machine_to_phys_mapping
-#define machine_to_phys_mapping ((unsigned long *)MACH2PHYS_VIRT_START)
-#endif
-
-/* 32-/64-bit invariability for control interfaces (domctl/sysctl). */
-#if defined(__XEN__) || defined(__XEN_TOOLS__)
-#undef ___DEFINE_XEN_GUEST_HANDLE
-#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
- typedef struct { type *p; } \
- __guest_handle_ ## name; \
- typedef struct { union { type *p; uint64_aligned_t q; }; } \
- __guest_handle_64_ ## name
-#undef set_xen_guest_handle_raw
-#define set_xen_guest_handle_raw(hnd, val) \
- do { if ( sizeof(hnd) == 8 ) *(uint64_t *)&(hnd) = 0; \
- (hnd).p = val; \
- } while ( 0 )
-#define uint64_aligned_t uint64_t __attribute__((aligned(8)))
-#define __XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name
-#define XEN_GUEST_HANDLE_64(name) __XEN_GUEST_HANDLE_64(name)
-#endif
-
-#ifndef __ASSEMBLY__
-
-struct cpu_user_regs {
- uint32_t ebx;
- uint32_t ecx;
- uint32_t edx;
- uint32_t esi;
- uint32_t edi;
- uint32_t ebp;
- uint32_t eax;
- uint16_t error_code; /* private */
- uint16_t entry_vector; /* private */
- uint32_t eip;
- uint16_t cs;
- uint8_t saved_upcall_mask;
- uint8_t _pad0;
- uint32_t eflags; /* eflags.IF == !saved_upcall_mask */
- uint32_t esp;
- uint16_t ss, _pad1;
- uint16_t es, _pad2;
- uint16_t ds, _pad3;
- uint16_t fs, _pad4;
- uint16_t gs, _pad5;
-};
-typedef struct cpu_user_regs cpu_user_regs_t;
-DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
-
-/*
- * Page-directory addresses above 4GB do not fit into architectural %cr3.
- * When accessing %cr3, or equivalent field in vcpu_guest_context, guests
- * must use the following accessor macros to pack/unpack valid MFNs.
- */
-#define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20))
-#define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20))
-
-struct arch_vcpu_info {
- unsigned long cr2;
- unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */
-};
-typedef struct arch_vcpu_info arch_vcpu_info_t;
-
-struct xen_callback {
- unsigned long cs;
- unsigned long eip;
-};
-typedef struct xen_callback xen_callback_t;
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * xen-x86_64.h
- *
- * Guest OS interface to x86 64-bit Xen.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2004-2006, K A Fraser
- */
-
-#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
-#define __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
-
-/*
- * Hypercall interface:
- * Input: %rdi, %rsi, %rdx, %r10, %r8, %r9 (arguments 1-6)
- * Output: %rax
- * Access is via hypercall page (set up by guest loader or via a Xen MSR):
- * call hypercall_page + hypercall-number * 32
- * Clobbered: argument registers (e.g., 2-arg hypercall clobbers %rdi,%rsi)
- */
-
-/*
- * 64-bit segment selectors
- * These flat segments are in the Xen-private section of every GDT. Since these
- * are also present in the initial GDT, many OSes will be able to avoid
- * installing their own GDT.
- */
-
-#define FLAT_RING3_CS32 0xe023 /* GDT index 260 */
-#define FLAT_RING3_CS64 0xe033 /* GDT index 261 */
-#define FLAT_RING3_DS32 0xe02b /* GDT index 262 */
-#define FLAT_RING3_DS64 0x0000 /* NULL selector */
-#define FLAT_RING3_SS32 0xe02b /* GDT index 262 */
-#define FLAT_RING3_SS64 0xe02b /* GDT index 262 */
-
-#define FLAT_KERNEL_DS64 FLAT_RING3_DS64
-#define FLAT_KERNEL_DS32 FLAT_RING3_DS32
-#define FLAT_KERNEL_DS FLAT_KERNEL_DS64
-#define FLAT_KERNEL_CS64 FLAT_RING3_CS64
-#define FLAT_KERNEL_CS32 FLAT_RING3_CS32
-#define FLAT_KERNEL_CS FLAT_KERNEL_CS64
-#define FLAT_KERNEL_SS64 FLAT_RING3_SS64
-#define FLAT_KERNEL_SS32 FLAT_RING3_SS32
-#define FLAT_KERNEL_SS FLAT_KERNEL_SS64
-
-#define FLAT_USER_DS64 FLAT_RING3_DS64
-#define FLAT_USER_DS32 FLAT_RING3_DS32
-#define FLAT_USER_DS FLAT_USER_DS64
-#define FLAT_USER_CS64 FLAT_RING3_CS64
-#define FLAT_USER_CS32 FLAT_RING3_CS32
-#define FLAT_USER_CS FLAT_USER_CS64
-#define FLAT_USER_SS64 FLAT_RING3_SS64
-#define FLAT_USER_SS32 FLAT_RING3_SS32
-#define FLAT_USER_SS FLAT_USER_SS64
-
-#define __HYPERVISOR_VIRT_START 0xFFFF800000000000
-#define __HYPERVISOR_VIRT_END 0xFFFF880000000000
-#define __MACH2PHYS_VIRT_START 0xFFFF800000000000
-#define __MACH2PHYS_VIRT_END 0xFFFF804000000000
-
-#ifndef HYPERVISOR_VIRT_START
-#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
-#define HYPERVISOR_VIRT_END mk_unsigned_long(__HYPERVISOR_VIRT_END)
-#endif
-
-#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START)
-#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END)
-#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3)
-#ifndef machine_to_phys_mapping
-#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
-#endif
-
-/*
- * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base)
- * @which == SEGBASE_* ; @base == 64-bit base address
- * Returns 0 on success.
- */
-#define SEGBASE_FS 0
-#define SEGBASE_GS_USER 1
-#define SEGBASE_GS_KERNEL 2
-#define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */
-
-/*
- * int HYPERVISOR_iret(void)
- * All arguments are on the kernel stack, in the following format.
- * Never returns if successful. Current kernel context is lost.
- * The saved CS is mapped as follows:
- * RING0 -> RING3 kernel mode.
- * RING1 -> RING3 kernel mode.
- * RING2 -> RING3 kernel mode.
- * RING3 -> RING3 user mode.
- * However RING0 indicates that the guest kernel should return to iteself
- * directly with
- * orb $3,1*8(%rsp)
- * iretq
- * If flags contains VGCF_in_syscall:
- * Restore RAX, RIP, RFLAGS, RSP.
- * Discard R11, RCX, CS, SS.
- * Otherwise:
- * Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP.
- * All other registers are saved on hypercall entry and restored to user.
- */
-/* Guest exited in SYSCALL context? Return to guest with SYSRET? */
-#define _VGCF_in_syscall 8
-#define VGCF_in_syscall (1<<_VGCF_in_syscall)
-#define VGCF_IN_SYSCALL VGCF_in_syscall
-
-#ifndef __ASSEMBLY__
-
-struct iret_context {
- /* Top of stack (%rsp at point of hypercall). */
- uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
- /* Bottom of iret stack frame. */
-};
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-/* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */
-#define __DECL_REG(name) union { \
- uint64_t r ## name, e ## name; \
- uint32_t _e ## name; \
-}
-#else
-/* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */
-#define __DECL_REG(name) uint64_t r ## name
-#endif
-
-struct cpu_user_regs {
- uint64_t r15;
- uint64_t r14;
- uint64_t r13;
- uint64_t r12;
- __DECL_REG(bp);
- __DECL_REG(bx);
- uint64_t r11;
- uint64_t r10;
- uint64_t r9;
- uint64_t r8;
- __DECL_REG(ax);
- __DECL_REG(cx);
- __DECL_REG(dx);
- __DECL_REG(si);
- __DECL_REG(di);
- uint32_t error_code; /* private */
- uint32_t entry_vector; /* private */
- __DECL_REG(ip);
- uint16_t cs, _pad0[1];
- uint8_t saved_upcall_mask;
- uint8_t _pad1[3];
- __DECL_REG(flags); /* rflags.IF == !saved_upcall_mask */
- __DECL_REG(sp);
- uint16_t ss, _pad2[3];
- uint16_t es, _pad3[3];
- uint16_t ds, _pad4[3];
- uint16_t fs, _pad5[3]; /* Non-zero => takes precedence over fs_base. */
- uint16_t gs, _pad6[3]; /* Non-zero => takes precedence over gs_base_usr. */
-};
-typedef struct cpu_user_regs cpu_user_regs_t;
-DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
-
-#undef __DECL_REG
-
-#define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12)
-#define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12)
-
-struct arch_vcpu_info {
- unsigned long cr2;
- unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
-};
-typedef struct arch_vcpu_info arch_vcpu_info_t;
-
-typedef unsigned long xen_callback_t;
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * arch-x86/xen.h
- *
- * Guest OS interface to x86 Xen.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2004-2006, K A Fraser
- */
-
-#include "../xen.h"
-
-#ifndef __XEN_PUBLIC_ARCH_X86_XEN_H__
-#define __XEN_PUBLIC_ARCH_X86_XEN_H__
-
-/* Structural guest handles introduced in 0x00030201. */
-#if __XEN_INTERFACE_VERSION__ >= 0x00030201
-#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
- typedef struct { type *p; } __guest_handle_ ## name
-#else
-#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
- typedef type * __guest_handle_ ## name
-#endif
-
-/*
- * XEN_GUEST_HANDLE represents a guest pointer, when passed as a field
- * in a struct in memory.
- * XEN_GUEST_HANDLE_PARAM represent a guest pointer, when passed as an
- * hypercall argument.
- * XEN_GUEST_HANDLE_PARAM and XEN_GUEST_HANDLE are the same on X86 but
- * they might not be on other architectures.
- */
-#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
- ___DEFINE_XEN_GUEST_HANDLE(name, type); \
- ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
-#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
-#define __XEN_GUEST_HANDLE(name) __guest_handle_ ## name
-#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name)
-#define XEN_GUEST_HANDLE_PARAM(name) XEN_GUEST_HANDLE(name)
-#define set_xen_guest_handle_raw(hnd, val) do { (hnd).p = val; } while (0)
-#ifdef __XEN_TOOLS__
-#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0)
-#endif
-#define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val)
-
-#if defined(__i386__)
-#include "xen-x86_32.h"
-#elif defined(__x86_64__)
-#include "xen-x86_64.h"
-#endif
-
-#ifndef __ASSEMBLY__
-typedef unsigned long xen_pfn_t;
-#define PRI_xen_pfn "lx"
-#endif
-
-#define XEN_HAVE_PV_GUEST_ENTRY 1
-
-#define XEN_HAVE_PV_UPCALL_MASK 1
-
-/*
- * `incontents 200 segdesc Segment Descriptor Tables
- */
-/*
- * ` enum neg_errnoval
- * ` HYPERVISOR_set_gdt(const xen_pfn_t frames[], unsigned int entries);
- * `
- */
-/*
- * A number of GDT entries are reserved by Xen. These are not situated at the
- * start of the GDT because some stupid OSes export hard-coded selector values
- * in their ABI. These hard-coded values are always near the start of the GDT,
- * so Xen places itself out of the way, at the far end of the GDT.
- *
- * NB The LDT is set using the MMUEXT_SET_LDT op of HYPERVISOR_mmuext_op
- */
-#define FIRST_RESERVED_GDT_PAGE 14
-#define FIRST_RESERVED_GDT_BYTE (FIRST_RESERVED_GDT_PAGE * 4096)
-#define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8)
-
-
-/*
- * ` enum neg_errnoval
- * ` HYPERVISOR_update_descriptor(u64 pa, u64 desc);
- * `
- * ` @pa The machine physical address of the descriptor to
- * ` update. Must be either a descriptor page or writable.
- * ` @desc The descriptor value to update, in the same format as a
- * ` native descriptor table entry.
- */
-
-/* Maximum number of virtual CPUs in legacy multi-processor guests. */
-#define XEN_LEGACY_MAX_VCPUS 32
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned long xen_ulong_t;
-#define PRI_xen_ulong "lx"
-
-/*
- * ` enum neg_errnoval
- * ` HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp);
- * `
- * Sets the stack segment and pointer for the current vcpu.
- */
-
-/*
- * ` enum neg_errnoval
- * ` HYPERVISOR_set_trap_table(const struct trap_info traps[]);
- * `
- */
-/*
- * Send an array of these to HYPERVISOR_set_trap_table().
- * Terminate the array with a sentinel entry, with traps[].address==0.
- * The privilege level specifies which modes may enter a trap via a software
- * interrupt. On x86/64, since rings 1 and 2 are unavailable, we allocate
- * privilege levels as follows:
- * Level == 0: Noone may enter
- * Level == 1: Kernel may enter
- * Level == 2: Kernel may enter
- * Level == 3: Everyone may enter
- */
-#define TI_GET_DPL(_ti) ((_ti)->flags & 3)
-#define TI_GET_IF(_ti) ((_ti)->flags & 4)
-#define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl))
-#define TI_SET_IF(_ti,_if) ((_ti)->flags |= ((!!(_if))<<2))
-struct trap_info {
- uint8_t vector; /* exception vector */
- uint8_t flags; /* 0-3: privilege level; 4: clear event enable? */
- uint16_t cs; /* code selector */
- unsigned long address; /* code offset */
-};
-typedef struct trap_info trap_info_t;
-DEFINE_XEN_GUEST_HANDLE(trap_info_t);
-
-typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
-
-/*
- * The following is all CPU context. Note that the fpu_ctxt block is filled
- * in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
- *
- * Also note that when calling DOMCTL_setvcpucontext and VCPU_initialise
- * for HVM and PVH guests, not all information in this structure is updated:
- *
- * - For HVM guests, the structures read include: fpu_ctxt (if
- * VGCT_I387_VALID is set), flags, user_regs, debugreg[*]
- *
- * - PVH guests are the same as HVM guests, but additionally use ctrlreg[3] to
- * set cr3. All other fields not used should be set to 0.
- */
-struct vcpu_guest_context {
- /* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
- struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */
-#define VGCF_I387_VALID (1<<0)
-#define VGCF_IN_KERNEL (1<<2)
-#define _VGCF_i387_valid 0
-#define VGCF_i387_valid (1<<_VGCF_i387_valid)
-#define _VGCF_in_kernel 2
-#define VGCF_in_kernel (1<<_VGCF_in_kernel)
-#define _VGCF_failsafe_disables_events 3
-#define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events)
-#define _VGCF_syscall_disables_events 4
-#define VGCF_syscall_disables_events (1<<_VGCF_syscall_disables_events)
-#define _VGCF_online 5
-#define VGCF_online (1<<_VGCF_online)
- unsigned long flags; /* VGCF_* flags */
- struct cpu_user_regs user_regs; /* User-level CPU registers */
- struct trap_info trap_ctxt[256]; /* Virtual IDT */
- unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */
- unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
- unsigned long kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */
- /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */
- unsigned long ctrlreg[8]; /* CR0-CR7 (control registers) */
- unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */
-#ifdef __i386__
- unsigned long event_callback_cs; /* CS:EIP of event callback */
- unsigned long event_callback_eip;
- unsigned long failsafe_callback_cs; /* CS:EIP of failsafe callback */
- unsigned long failsafe_callback_eip;
-#else
- unsigned long event_callback_eip;
- unsigned long failsafe_callback_eip;
-#ifdef __XEN__
- union {
- unsigned long syscall_callback_eip;
- struct {
- unsigned int event_callback_cs; /* compat CS of event cb */
- unsigned int failsafe_callback_cs; /* compat CS of failsafe cb */
- };
- };
-#else
- unsigned long syscall_callback_eip;
-#endif
-#endif
- unsigned long vm_assist; /* VMASST_TYPE_* bitmap */
-#ifdef __x86_64__
- /* Segment base addresses. */
- uint64_t fs_base;
- uint64_t gs_base_kernel;
- uint64_t gs_base_user;
-#endif
-};
-typedef struct vcpu_guest_context vcpu_guest_context_t;
-DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
-
-struct arch_shared_info {
- /*
- * Number of valid entries in the p2m table(s) anchored at
- * pfn_to_mfn_frame_list_list and/or p2m_vaddr.
- */
- unsigned long max_pfn;
- /*
- * Frame containing list of mfns containing list of mfns containing p2m.
- * A value of 0 indicates it has not yet been set up, ~0 indicates it has
- * been set to invalid e.g. due to the p2m being too large for the 3-level
- * p2m tree. In this case the linear mapper p2m list anchored at p2m_vaddr
- * is to be used.
- */
- xen_pfn_t pfn_to_mfn_frame_list_list;
- unsigned long nmi_reason;
- /*
- * Following three fields are valid if p2m_cr3 contains a value different
- * from 0.
- * p2m_cr3 is the root of the address space where p2m_vaddr is valid.
- * p2m_cr3 is in the same format as a cr3 value in the vcpu register state
- * and holds the folded machine frame number (via xen_pfn_to_cr3) of a
- * L3 or L4 page table.
- * p2m_vaddr holds the virtual address of the linear p2m list. All entries
- * in the range [0...max_pfn[ are accessible via this pointer.
- * p2m_generation will be incremented by the guest before and after each
- * change of the mappings of the p2m list. p2m_generation starts at 0 and
- * a value with the least significant bit set indicates that a mapping
- * update is in progress. This allows guest external software (e.g. in Dom0)
- * to verify that read mappings are consistent and whether they have changed
- * since the last check.
- * Modifying a p2m element in the linear p2m list is allowed via an atomic
- * write only.
- */
- unsigned long p2m_cr3; /* cr3 value of the p2m address space */
- unsigned long p2m_vaddr; /* virtual address of the p2m list */
- unsigned long p2m_generation; /* generation count of p2m mapping */
-};
-typedef struct arch_shared_info arch_shared_info_t;
-
-#endif /* !__ASSEMBLY__ */
-
-/*
- * ` enum neg_errnoval
- * ` HYPERVISOR_fpu_taskswitch(int set);
- * `
- * Sets (if set!=0) or clears (if set==0) CR0.TS.
- */
-
-/*
- * ` enum neg_errnoval
- * ` HYPERVISOR_set_debugreg(int regno, unsigned long value);
- *
- * ` unsigned long
- * ` HYPERVISOR_get_debugreg(int regno);
- * For 0<=reg<=7, returns the debug register value.
- * For other values of reg, returns ((unsigned long)-EINVAL).
- * (Unfortunately, this interface is defective.)
- */
-
-/*
- * Prefix forces emulation of some non-trapping instructions.
- * Currently only CPUID.
- */
-#ifdef __ASSEMBLY__
-#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ;
-#define XEN_CPUID XEN_EMULATE_PREFIX cpuid
-#else
-#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; "
-#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid"
-#endif
-
-#endif /* __XEN_PUBLIC_ARCH_X86_XEN_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * arch-x86_32.h
- *
- * Guest OS interface to x86 32-bit Xen.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2004-2006, K A Fraser
- */
-
-#include "arch-x86/xen.h"
+++ /dev/null
-/******************************************************************************
- * arch-x86_64.h
- *
- * Guest OS interface to x86 64-bit Xen.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2004-2006, K A Fraser
- */
-
-#include "arch-x86/xen.h"
-
-/*
- * ` enum neg_errnoval
- * ` HYPERVISOR_set_callbacks(unsigned long event_selector,
- * ` unsigned long event_address,
- * ` unsigned long failsafe_selector,
- * ` unsigned long failsafe_address);
- * `
- * Register for callbacks on events. When an event (from an event
- * channel) occurs, event_address is used as the value of eip.
- *
- * A similar callback occurs if the segment selectors are invalid.
- * failsafe_address is used as the value of eip.
- *
- * On x86_64, event_selector and failsafe_selector are ignored (???).
- */
+++ /dev/null
-/******************************************************************************
- * callback.h
- *
- * Register guest OS callbacks with Xen.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2006, Ian Campbell
- */
-
-#ifndef __XEN_PUBLIC_CALLBACK_H__
-#define __XEN_PUBLIC_CALLBACK_H__
-
-#include "xen.h"
-
-/*
- * Prototype for this hypercall is:
- * long callback_op(int cmd, void *extra_args)
- * @cmd == CALLBACKOP_??? (callback operation).
- * @extra_args == Operation-specific extra arguments (NULL if none).
- */
-
-/* x86: Callback for event delivery. */
-#define CALLBACKTYPE_event 0
-
-/* x86: Failsafe callback when guest state cannot be restored by Xen. */
-#define CALLBACKTYPE_failsafe 1
-
-/* x86/64 hypervisor: Syscall by 64-bit guest app ('64-on-64-on-64'). */
-#define CALLBACKTYPE_syscall 2
-
-/*
- * x86/32 hypervisor: Only available on x86/32 when supervisor_mode_kernel
- * feature is enabled. Do not use this callback type in new code.
- */
-#define CALLBACKTYPE_sysenter_deprecated 3
-
-/* x86: Callback for NMI delivery. */
-#define CALLBACKTYPE_nmi 4
-
-/*
- * x86: sysenter is only available as follows:
- * - 32-bit hypervisor: with the supervisor_mode_kernel feature enabled
- * - 64-bit hypervisor: 32-bit guest applications on Intel CPUs
- * ('32-on-32-on-64', '32-on-64-on-64')
- * [nb. also 64-bit guest applications on Intel CPUs
- * ('64-on-64-on-64'), but syscall is preferred]
- */
-#define CALLBACKTYPE_sysenter 5
-
-/*
- * x86/64 hypervisor: Syscall by 32-bit guest app on AMD CPUs
- * ('32-on-32-on-64', '32-on-64-on-64')
- */
-#define CALLBACKTYPE_syscall32 7
-
-/*
- * Disable event deliver during callback? This flag is ignored for event and
- * NMI callbacks: event delivery is unconditionally disabled.
- */
-#define _CALLBACKF_mask_events 0
-#define CALLBACKF_mask_events (1U << _CALLBACKF_mask_events)
-
-/*
- * Register a callback.
- */
-#define CALLBACKOP_register 0
-struct callback_register {
- uint16_t type;
- uint16_t flags;
- xen_callback_t address;
-};
-typedef struct callback_register callback_register_t;
-DEFINE_XEN_GUEST_HANDLE(callback_register_t);
-
-/*
- * Unregister a callback.
- *
- * Not all callbacks can be unregistered. -EINVAL will be returned if
- * you attempt to unregister such a callback.
- */
-#define CALLBACKOP_unregister 1
-struct callback_unregister {
- uint16_t type;
- uint16_t _unused;
-};
-typedef struct callback_unregister callback_unregister_t;
-DEFINE_XEN_GUEST_HANDLE(callback_unregister_t);
-
-#if __XEN_INTERFACE_VERSION__ < 0x00030207
-#undef CALLBACKTYPE_sysenter
-#define CALLBACKTYPE_sysenter CALLBACKTYPE_sysenter_deprecated
-#endif
-
-#endif /* __XEN_PUBLIC_CALLBACK_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * dom0_ops.h
- *
- * Process command requests from domain-0 guest OS.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2002-2003, B Dragovic
- * Copyright (c) 2002-2006, K Fraser
- */
-
-#ifndef __XEN_PUBLIC_DOM0_OPS_H__
-#define __XEN_PUBLIC_DOM0_OPS_H__
-
-#include "xen.h"
-#include "platform.h"
-
-#if __XEN_INTERFACE_VERSION__ >= 0x00030204
-#error "dom0_ops.h is a compatibility interface only"
-#endif
-
-#define DOM0_INTERFACE_VERSION XENPF_INTERFACE_VERSION
-
-#define DOM0_SETTIME XENPF_settime
-#define dom0_settime xenpf_settime
-#define dom0_settime_t xenpf_settime_t
-
-#define DOM0_ADD_MEMTYPE XENPF_add_memtype
-#define dom0_add_memtype xenpf_add_memtype
-#define dom0_add_memtype_t xenpf_add_memtype_t
-
-#define DOM0_DEL_MEMTYPE XENPF_del_memtype
-#define dom0_del_memtype xenpf_del_memtype
-#define dom0_del_memtype_t xenpf_del_memtype_t
-
-#define DOM0_READ_MEMTYPE XENPF_read_memtype
-#define dom0_read_memtype xenpf_read_memtype
-#define dom0_read_memtype_t xenpf_read_memtype_t
-
-#define DOM0_MICROCODE XENPF_microcode_update
-#define dom0_microcode xenpf_microcode_update
-#define dom0_microcode_t xenpf_microcode_update_t
-
-#define DOM0_PLATFORM_QUIRK XENPF_platform_quirk
-#define dom0_platform_quirk xenpf_platform_quirk
-#define dom0_platform_quirk_t xenpf_platform_quirk_t
-
-typedef uint64_t cpumap_t;
-
-/* Unsupported legacy operation -- defined for API compatibility. */
-#define DOM0_MSR 15
-struct dom0_msr {
- /* IN variables. */
- uint32_t write;
- cpumap_t cpu_mask;
- uint32_t msr;
- uint32_t in1;
- uint32_t in2;
- /* OUT variables. */
- uint32_t out1;
- uint32_t out2;
-};
-typedef struct dom0_msr dom0_msr_t;
-DEFINE_XEN_GUEST_HANDLE(dom0_msr_t);
-
-/* Unsupported legacy operation -- defined for API compatibility. */
-#define DOM0_PHYSICAL_MEMORY_MAP 40
-struct dom0_memory_map_entry {
- uint64_t start, end;
- uint32_t flags; /* reserved */
- uint8_t is_ram;
-};
-typedef struct dom0_memory_map_entry dom0_memory_map_entry_t;
-DEFINE_XEN_GUEST_HANDLE(dom0_memory_map_entry_t);
-
-struct dom0_op {
- uint32_t cmd;
- uint32_t interface_version; /* DOM0_INTERFACE_VERSION */
- union {
- struct dom0_msr msr;
- struct dom0_settime settime;
- struct dom0_add_memtype add_memtype;
- struct dom0_del_memtype del_memtype;
- struct dom0_read_memtype read_memtype;
- struct dom0_microcode microcode;
- struct dom0_platform_quirk platform_quirk;
- struct dom0_memory_map_entry physical_memory_map;
- uint8_t pad[128];
- } u;
-};
-typedef struct dom0_op dom0_op_t;
-DEFINE_XEN_GUEST_HANDLE(dom0_op_t);
-
-#endif /* __XEN_PUBLIC_DOM0_OPS_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * domctl.h
- *
- * Domain management operations. For use by node control stack.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2002-2003, B Dragovic
- * Copyright (c) 2002-2006, K Fraser
- */
-
-#ifndef __XEN_PUBLIC_DOMCTL_H__
-#define __XEN_PUBLIC_DOMCTL_H__
-
-#if !defined(__XEN__) && !defined(__XEN_TOOLS__)
-#error "domctl operations are intended for use by node control tools only"
-#endif
-
-#include "xen.h"
-#include "grant_table.h"
-#include "hvm/save.h"
-#include "memory.h"
-
-#define XEN_DOMCTL_INTERFACE_VERSION 0x0000000a
-
-/*
- * NB. xen_domctl.domain is an IN/OUT parameter for this operation.
- * If it is specified as zero, an id is auto-allocated and returned.
- */
-/* XEN_DOMCTL_createdomain */
-struct xen_domctl_createdomain {
- /* IN parameters */
- uint32_t ssidref;
- xen_domain_handle_t handle;
- /* Is this an HVM guest (as opposed to a PVH or PV guest)? */
-#define _XEN_DOMCTL_CDF_hvm_guest 0
-#define XEN_DOMCTL_CDF_hvm_guest (1U<<_XEN_DOMCTL_CDF_hvm_guest)
- /* Use hardware-assisted paging if available? */
-#define _XEN_DOMCTL_CDF_hap 1
-#define XEN_DOMCTL_CDF_hap (1U<<_XEN_DOMCTL_CDF_hap)
- /* Should domain memory integrity be verifed by tboot during Sx? */
-#define _XEN_DOMCTL_CDF_s3_integrity 2
-#define XEN_DOMCTL_CDF_s3_integrity (1U<<_XEN_DOMCTL_CDF_s3_integrity)
- /* Disable out-of-sync shadow page tables? */
-#define _XEN_DOMCTL_CDF_oos_off 3
-#define XEN_DOMCTL_CDF_oos_off (1U<<_XEN_DOMCTL_CDF_oos_off)
- /* Is this a PVH guest (as opposed to an HVM or PV guest)? */
-#define _XEN_DOMCTL_CDF_pvh_guest 4
-#define XEN_DOMCTL_CDF_pvh_guest (1U<<_XEN_DOMCTL_CDF_pvh_guest)
- uint32_t flags;
-};
-typedef struct xen_domctl_createdomain xen_domctl_createdomain_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_createdomain_t);
-
-#if defined(__arm__) || defined(__aarch64__)
-#define XEN_DOMCTL_CONFIG_GIC_DEFAULT 0
-#define XEN_DOMCTL_CONFIG_GIC_V2 1
-#define XEN_DOMCTL_CONFIG_GIC_V3 2
-/* XEN_DOMCTL_configure_domain */
-struct xen_domctl_arm_configuredomain {
- /* IN/OUT parameters */
- uint8_t gic_version;
-};
-typedef struct xen_domctl_arm_configuredomain xen_domctl_arm_configuredomain_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_arm_configuredomain_t);
-#endif
-
-/* XEN_DOMCTL_getdomaininfo */
-struct xen_domctl_getdomaininfo {
- /* OUT variables. */
- domid_t domain; /* Also echoed in domctl.domain */
- /* Domain is scheduled to die. */
-#define _XEN_DOMINF_dying 0
-#define XEN_DOMINF_dying (1U<<_XEN_DOMINF_dying)
- /* Domain is an HVM guest (as opposed to a PV guest). */
-#define _XEN_DOMINF_hvm_guest 1
-#define XEN_DOMINF_hvm_guest (1U<<_XEN_DOMINF_hvm_guest)
- /* The guest OS has shut down. */
-#define _XEN_DOMINF_shutdown 2
-#define XEN_DOMINF_shutdown (1U<<_XEN_DOMINF_shutdown)
- /* Currently paused by control software. */
-#define _XEN_DOMINF_paused 3
-#define XEN_DOMINF_paused (1U<<_XEN_DOMINF_paused)
- /* Currently blocked pending an event. */
-#define _XEN_DOMINF_blocked 4
-#define XEN_DOMINF_blocked (1U<<_XEN_DOMINF_blocked)
- /* Domain is currently running. */
-#define _XEN_DOMINF_running 5
-#define XEN_DOMINF_running (1U<<_XEN_DOMINF_running)
- /* Being debugged. */
-#define _XEN_DOMINF_debugged 6
-#define XEN_DOMINF_debugged (1U<<_XEN_DOMINF_debugged)
-/* domain is PVH */
-#define _XEN_DOMINF_pvh_guest 7
-#define XEN_DOMINF_pvh_guest (1U<<_XEN_DOMINF_pvh_guest)
- /* XEN_DOMINF_shutdown guest-supplied code. */
-#define XEN_DOMINF_shutdownmask 255
-#define XEN_DOMINF_shutdownshift 16
- uint32_t flags; /* XEN_DOMINF_* */
- uint64_aligned_t tot_pages;
- uint64_aligned_t max_pages;
- uint64_aligned_t outstanding_pages;
- uint64_aligned_t shr_pages;
- uint64_aligned_t paged_pages;
- uint64_aligned_t shared_info_frame; /* GMFN of shared_info struct */
- uint64_aligned_t cpu_time;
- uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
-#define XEN_INVALID_MAX_VCPU_ID (~0U) /* Domain has no vcpus? */
- uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
- uint32_t ssidref;
- xen_domain_handle_t handle;
- uint32_t cpupool;
-};
-typedef struct xen_domctl_getdomaininfo xen_domctl_getdomaininfo_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_getdomaininfo_t);
-
-
-/* XEN_DOMCTL_getmemlist */
-struct xen_domctl_getmemlist {
- /* IN variables. */
- /* Max entries to write to output buffer. */
- uint64_aligned_t max_pfns;
- /* Start index in guest's page list. */
- uint64_aligned_t start_pfn;
- XEN_GUEST_HANDLE_64(uint64) buffer;
- /* OUT variables. */
- uint64_aligned_t num_pfns;
-};
-typedef struct xen_domctl_getmemlist xen_domctl_getmemlist_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_getmemlist_t);
-
-
-/* XEN_DOMCTL_getpageframeinfo */
-
-#define XEN_DOMCTL_PFINFO_LTAB_SHIFT 28
-#define XEN_DOMCTL_PFINFO_NOTAB (0x0U<<28)
-#define XEN_DOMCTL_PFINFO_L1TAB (0x1U<<28)
-#define XEN_DOMCTL_PFINFO_L2TAB (0x2U<<28)
-#define XEN_DOMCTL_PFINFO_L3TAB (0x3U<<28)
-#define XEN_DOMCTL_PFINFO_L4TAB (0x4U<<28)
-#define XEN_DOMCTL_PFINFO_LTABTYPE_MASK (0x7U<<28)
-#define XEN_DOMCTL_PFINFO_LPINTAB (0x1U<<31)
-#define XEN_DOMCTL_PFINFO_XTAB (0xfU<<28) /* invalid page */
-#define XEN_DOMCTL_PFINFO_XALLOC (0xeU<<28) /* allocate-only page */
-#define XEN_DOMCTL_PFINFO_BROKEN (0xdU<<28) /* broken page */
-#define XEN_DOMCTL_PFINFO_LTAB_MASK (0xfU<<28)
-
-struct xen_domctl_getpageframeinfo {
- /* IN variables. */
- uint64_aligned_t gmfn; /* GMFN to query */
- /* OUT variables. */
- /* Is the page PINNED to a type? */
- uint32_t type; /* see above type defs */
-};
-typedef struct xen_domctl_getpageframeinfo xen_domctl_getpageframeinfo_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo_t);
-
-
-/* XEN_DOMCTL_getpageframeinfo2 */
-struct xen_domctl_getpageframeinfo2 {
- /* IN variables. */
- uint64_aligned_t num;
- /* IN/OUT variables. */
- XEN_GUEST_HANDLE_64(uint32) array;
-};
-typedef struct xen_domctl_getpageframeinfo2 xen_domctl_getpageframeinfo2_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo2_t);
-
-/* XEN_DOMCTL_getpageframeinfo3 */
-struct xen_domctl_getpageframeinfo3 {
- /* IN variables. */
- uint64_aligned_t num;
- /* IN/OUT variables. */
- XEN_GUEST_HANDLE_64(xen_pfn_t) array;
-};
-
-
-/*
- * Control shadow pagetables operation
- */
-/* XEN_DOMCTL_shadow_op */
-
-/* Disable shadow mode. */
-#define XEN_DOMCTL_SHADOW_OP_OFF 0
-
-/* Enable shadow mode (mode contains ORed XEN_DOMCTL_SHADOW_ENABLE_* flags). */
-#define XEN_DOMCTL_SHADOW_OP_ENABLE 32
-
-/* Log-dirty bitmap operations. */
- /* Return the bitmap and clean internal copy for next round. */
-#define XEN_DOMCTL_SHADOW_OP_CLEAN 11
- /* Return the bitmap but do not modify internal copy. */
-#define XEN_DOMCTL_SHADOW_OP_PEEK 12
-
-/* Memory allocation accessors. */
-#define XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION 30
-#define XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION 31
-
-/* Legacy enable operations. */
- /* Equiv. to ENABLE with no mode flags. */
-#define XEN_DOMCTL_SHADOW_OP_ENABLE_TEST 1
- /* Equiv. to ENABLE with mode flag ENABLE_LOG_DIRTY. */
-#define XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY 2
- /* Equiv. to ENABLE with mode flags ENABLE_REFCOUNT and ENABLE_TRANSLATE. */
-#define XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE 3
-
-/* Mode flags for XEN_DOMCTL_SHADOW_OP_ENABLE. */
- /*
- * Shadow pagetables are refcounted: guest does not use explicit mmu
- * operations nor write-protect its pagetables.
- */
-#define XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT (1 << 1)
- /*
- * Log pages in a bitmap as they are dirtied.
- * Used for live relocation to determine which pages must be re-sent.
- */
-#define XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY (1 << 2)
- /*
- * Automatically translate GPFNs into MFNs.
- */
-#define XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE (1 << 3)
- /*
- * Xen does not steal virtual address space from the guest.
- * Requires HVM support.
- */
-#define XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL (1 << 4)
-
-struct xen_domctl_shadow_op_stats {
- uint32_t fault_count;
- uint32_t dirty_count;
-};
-typedef struct xen_domctl_shadow_op_stats xen_domctl_shadow_op_stats_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_stats_t);
-
-struct xen_domctl_shadow_op {
- /* IN variables. */
- uint32_t op; /* XEN_DOMCTL_SHADOW_OP_* */
-
- /* OP_ENABLE */
- uint32_t mode; /* XEN_DOMCTL_SHADOW_ENABLE_* */
-
- /* OP_GET_ALLOCATION / OP_SET_ALLOCATION */
- uint32_t mb; /* Shadow memory allocation in MB */
-
- /* OP_PEEK / OP_CLEAN */
- XEN_GUEST_HANDLE_64(uint8) dirty_bitmap;
- uint64_aligned_t pages; /* Size of buffer. Updated with actual size. */
- struct xen_domctl_shadow_op_stats stats;
-};
-typedef struct xen_domctl_shadow_op xen_domctl_shadow_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_t);
-
-
-/* XEN_DOMCTL_max_mem */
-struct xen_domctl_max_mem {
- /* IN variables. */
- uint64_aligned_t max_memkb;
-};
-typedef struct xen_domctl_max_mem xen_domctl_max_mem_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_mem_t);
-
-
-/* XEN_DOMCTL_setvcpucontext */
-/* XEN_DOMCTL_getvcpucontext */
-struct xen_domctl_vcpucontext {
- uint32_t vcpu; /* IN */
- XEN_GUEST_HANDLE_64(vcpu_guest_context_t) ctxt; /* IN/OUT */
-};
-typedef struct xen_domctl_vcpucontext xen_domctl_vcpucontext_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpucontext_t);
-
-
-/* XEN_DOMCTL_getvcpuinfo */
-struct xen_domctl_getvcpuinfo {
- /* IN variables. */
- uint32_t vcpu;
- /* OUT variables. */
- uint8_t online; /* currently online (not hotplugged)? */
- uint8_t blocked; /* blocked waiting for an event? */
- uint8_t running; /* currently scheduled on its CPU? */
- uint64_aligned_t cpu_time; /* total cpu time consumed (ns) */
- uint32_t cpu; /* current mapping */
-};
-typedef struct xen_domctl_getvcpuinfo xen_domctl_getvcpuinfo_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_getvcpuinfo_t);
-
-
-/* Get/set the NUMA node(s) with which the guest has affinity with. */
-/* XEN_DOMCTL_setnodeaffinity */
-/* XEN_DOMCTL_getnodeaffinity */
-struct xen_domctl_nodeaffinity {
- struct xenctl_bitmap nodemap;/* IN */
-};
-typedef struct xen_domctl_nodeaffinity xen_domctl_nodeaffinity_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_nodeaffinity_t);
-
-
-/* Get/set which physical cpus a vcpu can execute on. */
-/* XEN_DOMCTL_setvcpuaffinity */
-/* XEN_DOMCTL_getvcpuaffinity */
-struct xen_domctl_vcpuaffinity {
- /* IN variables. */
- uint32_t vcpu;
- /* Set/get the hard affinity for vcpu */
-#define _XEN_VCPUAFFINITY_HARD 0
-#define XEN_VCPUAFFINITY_HARD (1U<<_XEN_VCPUAFFINITY_HARD)
- /* Set/get the soft affinity for vcpu */
-#define _XEN_VCPUAFFINITY_SOFT 1
-#define XEN_VCPUAFFINITY_SOFT (1U<<_XEN_VCPUAFFINITY_SOFT)
- uint32_t flags;
- /*
- * IN/OUT variables.
- *
- * Both are IN/OUT for XEN_DOMCTL_setvcpuaffinity, in which case they
- * contain effective hard or/and soft affinity. That is, upon successful
- * return, cpumap_soft, contains the intersection of the soft affinity,
- * hard affinity and the cpupool's online CPUs for the domain (if
- * XEN_VCPUAFFINITY_SOFT was set in flags). cpumap_hard contains the
- * intersection between hard affinity and the cpupool's online CPUs (if
- * XEN_VCPUAFFINITY_HARD was set in flags).
- *
- * Both are OUT-only for XEN_DOMCTL_getvcpuaffinity, in which case they
- * contain the plain hard and/or soft affinity masks that were set during
- * previous successful calls to XEN_DOMCTL_setvcpuaffinity (or the
- * default values), without intersecting or altering them in any way.
- */
- struct xenctl_bitmap cpumap_hard;
- struct xenctl_bitmap cpumap_soft;
-};
-typedef struct xen_domctl_vcpuaffinity xen_domctl_vcpuaffinity_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpuaffinity_t);
-
-
-/* XEN_DOMCTL_max_vcpus */
-struct xen_domctl_max_vcpus {
- uint32_t max; /* maximum number of vcpus */
-};
-typedef struct xen_domctl_max_vcpus xen_domctl_max_vcpus_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_vcpus_t);
-
-
-/* XEN_DOMCTL_scheduler_op */
-/* Scheduler types. */
-#define XEN_SCHEDULER_SEDF 4
-#define XEN_SCHEDULER_CREDIT 5
-#define XEN_SCHEDULER_CREDIT2 6
-#define XEN_SCHEDULER_ARINC653 7
-#define XEN_SCHEDULER_RTDS 8
-
-/* Set or get info? */
-#define XEN_DOMCTL_SCHEDOP_putinfo 0
-#define XEN_DOMCTL_SCHEDOP_getinfo 1
-struct xen_domctl_scheduler_op {
- uint32_t sched_id; /* XEN_SCHEDULER_* */
- uint32_t cmd; /* XEN_DOMCTL_SCHEDOP_* */
- union {
- struct xen_domctl_sched_sedf {
- uint64_aligned_t period;
- uint64_aligned_t slice;
- uint64_aligned_t latency;
- uint32_t extratime;
- uint32_t weight;
- } sedf;
- struct xen_domctl_sched_credit {
- uint16_t weight;
- uint16_t cap;
- } credit;
- struct xen_domctl_sched_credit2 {
- uint16_t weight;
- } credit2;
- struct xen_domctl_sched_rtds {
- uint32_t period;
- uint32_t budget;
- } rtds;
- } u;
-};
-typedef struct xen_domctl_scheduler_op xen_domctl_scheduler_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_scheduler_op_t);
-
-
-/* XEN_DOMCTL_setdomainhandle */
-struct xen_domctl_setdomainhandle {
- xen_domain_handle_t handle;
-};
-typedef struct xen_domctl_setdomainhandle xen_domctl_setdomainhandle_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdomainhandle_t);
-
-
-/* XEN_DOMCTL_setdebugging */
-struct xen_domctl_setdebugging {
- uint8_t enable;
-};
-typedef struct xen_domctl_setdebugging xen_domctl_setdebugging_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdebugging_t);
-
-
-/* XEN_DOMCTL_irq_permission */
-struct xen_domctl_irq_permission {
- uint8_t pirq;
- uint8_t allow_access; /* flag to specify enable/disable of IRQ access */
-};
-typedef struct xen_domctl_irq_permission xen_domctl_irq_permission_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_irq_permission_t);
-
-
-/* XEN_DOMCTL_iomem_permission */
-struct xen_domctl_iomem_permission {
- uint64_aligned_t first_mfn;/* first page (physical page number) in range */
- uint64_aligned_t nr_mfns; /* number of pages in range (>0) */
- uint8_t allow_access; /* allow (!0) or deny (0) access to range? */
-};
-typedef struct xen_domctl_iomem_permission xen_domctl_iomem_permission_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_iomem_permission_t);
-
-
-/* XEN_DOMCTL_ioport_permission */
-struct xen_domctl_ioport_permission {
- uint32_t first_port; /* first port int range */
- uint32_t nr_ports; /* size of port range */
- uint8_t allow_access; /* allow or deny access to range? */
-};
-typedef struct xen_domctl_ioport_permission xen_domctl_ioport_permission_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_permission_t);
-
-
-/* XEN_DOMCTL_hypercall_init */
-struct xen_domctl_hypercall_init {
- uint64_aligned_t gmfn; /* GMFN to be initialised */
-};
-typedef struct xen_domctl_hypercall_init xen_domctl_hypercall_init_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_hypercall_init_t);
-
-
-/* XEN_DOMCTL_settimeoffset */
-struct xen_domctl_settimeoffset {
- int32_t time_offset_seconds; /* applied to domain wallclock time */
-};
-typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t);
-
-/* XEN_DOMCTL_gethvmcontext */
-/* XEN_DOMCTL_sethvmcontext */
-typedef struct xen_domctl_hvmcontext {
- uint32_t size; /* IN/OUT: size of buffer / bytes filled */
- XEN_GUEST_HANDLE_64(uint8) buffer; /* IN/OUT: data, or call
- * gethvmcontext with NULL
- * buffer to get size req'd */
-} xen_domctl_hvmcontext_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t);
-
-
-/* XEN_DOMCTL_set_address_size */
-/* XEN_DOMCTL_get_address_size */
-typedef struct xen_domctl_address_size {
- uint32_t size;
-} xen_domctl_address_size_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_address_size_t);
-
-
-/* XEN_DOMCTL_sendtrigger */
-#define XEN_DOMCTL_SENDTRIGGER_NMI 0
-#define XEN_DOMCTL_SENDTRIGGER_RESET 1
-#define XEN_DOMCTL_SENDTRIGGER_INIT 2
-#define XEN_DOMCTL_SENDTRIGGER_POWER 3
-#define XEN_DOMCTL_SENDTRIGGER_SLEEP 4
-struct xen_domctl_sendtrigger {
- uint32_t trigger; /* IN */
- uint32_t vcpu; /* IN */
-};
-typedef struct xen_domctl_sendtrigger xen_domctl_sendtrigger_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_sendtrigger_t);
-
-
-/* Assign PCI device to HVM guest. Sets up IOMMU structures. */
-/* XEN_DOMCTL_assign_device */
-/* XEN_DOMCTL_test_assign_device */
-/* XEN_DOMCTL_deassign_device */
-struct xen_domctl_assign_device {
- uint32_t machine_sbdf; /* machine PCI ID of assigned device */
-};
-typedef struct xen_domctl_assign_device xen_domctl_assign_device_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_assign_device_t);
-
-/* Retrieve sibling devices infomation of machine_sbdf */
-/* XEN_DOMCTL_get_device_group */
-struct xen_domctl_get_device_group {
- uint32_t machine_sbdf; /* IN */
- uint32_t max_sdevs; /* IN */
- uint32_t num_sdevs; /* OUT */
- XEN_GUEST_HANDLE_64(uint32) sdev_array; /* OUT */
-};
-typedef struct xen_domctl_get_device_group xen_domctl_get_device_group_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_get_device_group_t);
-
-/* Pass-through interrupts: bind real irq -> hvm devfn. */
-/* XEN_DOMCTL_bind_pt_irq */
-/* XEN_DOMCTL_unbind_pt_irq */
-typedef enum pt_irq_type_e {
- PT_IRQ_TYPE_PCI,
- PT_IRQ_TYPE_ISA,
- PT_IRQ_TYPE_MSI,
- PT_IRQ_TYPE_MSI_TRANSLATE,
-} pt_irq_type_t;
-struct xen_domctl_bind_pt_irq {
- uint32_t machine_irq;
- pt_irq_type_t irq_type;
- uint32_t hvm_domid;
-
- union {
- struct {
- uint8_t isa_irq;
- } isa;
- struct {
- uint8_t bus;
- uint8_t device;
- uint8_t intx;
- } pci;
- struct {
- uint8_t gvec;
- uint32_t gflags;
- uint64_aligned_t gtable;
- } msi;
- } u;
-};
-typedef struct xen_domctl_bind_pt_irq xen_domctl_bind_pt_irq_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_bind_pt_irq_t);
-
-
-/* Bind machine I/O address range -> HVM address range. */
-/* XEN_DOMCTL_memory_mapping */
-#define DPCI_ADD_MAPPING 1
-#define DPCI_REMOVE_MAPPING 0
-struct xen_domctl_memory_mapping {
- uint64_aligned_t first_gfn; /* first page (hvm guest phys page) in range */
- uint64_aligned_t first_mfn; /* first page (machine page) in range */
- uint64_aligned_t nr_mfns; /* number of pages in range (>0) */
- uint32_t add_mapping; /* add or remove mapping */
- uint32_t padding; /* padding for 64-bit aligned structure */
-};
-typedef struct xen_domctl_memory_mapping xen_domctl_memory_mapping_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_memory_mapping_t);
-
-
-/* Bind machine I/O port range -> HVM I/O port range. */
-/* XEN_DOMCTL_ioport_mapping */
-struct xen_domctl_ioport_mapping {
- uint32_t first_gport; /* first guest IO port*/
- uint32_t first_mport; /* first machine IO port */
- uint32_t nr_ports; /* size of port range */
- uint32_t add_mapping; /* add or remove mapping */
-};
-typedef struct xen_domctl_ioport_mapping xen_domctl_ioport_mapping_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_mapping_t);
-
-
-/*
- * Pin caching type of RAM space for x86 HVM domU.
- */
-/* XEN_DOMCTL_pin_mem_cacheattr */
-/* Caching types: these happen to be the same as x86 MTRR/PAT type codes. */
-#define XEN_DOMCTL_MEM_CACHEATTR_UC 0
-#define XEN_DOMCTL_MEM_CACHEATTR_WC 1
-#define XEN_DOMCTL_MEM_CACHEATTR_WT 4
-#define XEN_DOMCTL_MEM_CACHEATTR_WP 5
-#define XEN_DOMCTL_MEM_CACHEATTR_WB 6
-#define XEN_DOMCTL_MEM_CACHEATTR_UCM 7
-#define XEN_DOMCTL_DELETE_MEM_CACHEATTR (~(uint32_t)0)
-struct xen_domctl_pin_mem_cacheattr {
- uint64_aligned_t start, end;
- uint32_t type; /* XEN_DOMCTL_MEM_CACHEATTR_* */
-};
-typedef struct xen_domctl_pin_mem_cacheattr xen_domctl_pin_mem_cacheattr_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_pin_mem_cacheattr_t);
-
-
-/* XEN_DOMCTL_set_ext_vcpucontext */
-/* XEN_DOMCTL_get_ext_vcpucontext */
-struct xen_domctl_ext_vcpucontext {
- /* IN: VCPU that this call applies to. */
- uint32_t vcpu;
- /*
- * SET: Size of struct (IN)
- * GET: Size of struct (OUT, up to 128 bytes)
- */
- uint32_t size;
-#if defined(__i386__) || defined(__x86_64__)
- /* SYSCALL from 32-bit mode and SYSENTER callback information. */
- /* NB. SYSCALL from 64-bit mode is contained in vcpu_guest_context_t */
- uint64_aligned_t syscall32_callback_eip;
- uint64_aligned_t sysenter_callback_eip;
- uint16_t syscall32_callback_cs;
- uint16_t sysenter_callback_cs;
- uint8_t syscall32_disables_events;
- uint8_t sysenter_disables_events;
-#if defined(__GNUC__)
- union {
- uint64_aligned_t mcg_cap;
- struct hvm_vmce_vcpu vmce;
- };
-#else
- struct hvm_vmce_vcpu vmce;
-#endif
-#endif
-};
-typedef struct xen_domctl_ext_vcpucontext xen_domctl_ext_vcpucontext_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_ext_vcpucontext_t);
-
-/*
- * Set the target domain for a domain
- */
-/* XEN_DOMCTL_set_target */
-struct xen_domctl_set_target {
- domid_t target;
-};
-typedef struct xen_domctl_set_target xen_domctl_set_target_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_target_t);
-
-#if defined(__i386__) || defined(__x86_64__)
-# define XEN_CPUID_INPUT_UNUSED 0xFFFFFFFF
-/* XEN_DOMCTL_set_cpuid */
-struct xen_domctl_cpuid {
- uint32_t input[2];
- uint32_t eax;
- uint32_t ebx;
- uint32_t ecx;
- uint32_t edx;
-};
-typedef struct xen_domctl_cpuid xen_domctl_cpuid_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_cpuid_t);
-#endif
-
-/*
- * Arranges that if the domain suspends (specifically, if it shuts
- * down with code SHUTDOWN_suspend), this event channel will be
- * notified.
- *
- * This is _instead of_ the usual notification to the global
- * VIRQ_DOM_EXC. (In most systems that pirq is owned by xenstored.)
- *
- * Only one subscription per domain is possible. Last subscriber
- * wins; others are silently displaced.
- *
- * NB that contrary to the rather general name, it only applies to
- * domain shutdown with code suspend. Shutdown for other reasons
- * (including crash), and domain death, are notified to VIRQ_DOM_EXC
- * regardless.
- */
-/* XEN_DOMCTL_subscribe */
-struct xen_domctl_subscribe {
- uint32_t port; /* IN */
-};
-typedef struct xen_domctl_subscribe xen_domctl_subscribe_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_subscribe_t);
-
-/*
- * Define the maximum machine address size which should be allocated
- * to a guest.
- */
-/* XEN_DOMCTL_set_machine_address_size */
-/* XEN_DOMCTL_get_machine_address_size */
-
-/*
- * Do not inject spurious page faults into this domain.
- */
-/* XEN_DOMCTL_suppress_spurious_page_faults */
-
-/* XEN_DOMCTL_debug_op */
-#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF 0
-#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON 1
-struct xen_domctl_debug_op {
- uint32_t op; /* IN */
- uint32_t vcpu; /* IN */
-};
-typedef struct xen_domctl_debug_op xen_domctl_debug_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_debug_op_t);
-
-/*
- * Request a particular record from the HVM context
- */
-/* XEN_DOMCTL_gethvmcontext_partial */
-typedef struct xen_domctl_hvmcontext_partial {
- uint32_t type; /* IN: Type of record required */
- uint32_t instance; /* IN: Instance of that type */
- XEN_GUEST_HANDLE_64(uint8) buffer; /* OUT: buffer to write record into */
-} xen_domctl_hvmcontext_partial_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_partial_t);
-
-/* XEN_DOMCTL_disable_migrate */
-typedef struct xen_domctl_disable_migrate {
- uint32_t disable; /* IN: 1: disable migration and restore */
-} xen_domctl_disable_migrate_t;
-
-
-/* XEN_DOMCTL_gettscinfo */
-/* XEN_DOMCTL_settscinfo */
-struct xen_guest_tsc_info {
- uint32_t tsc_mode;
- uint32_t gtsc_khz;
- uint32_t incarnation;
- uint32_t pad;
- uint64_aligned_t elapsed_nsec;
-};
-typedef struct xen_guest_tsc_info xen_guest_tsc_info_t;
-DEFINE_XEN_GUEST_HANDLE(xen_guest_tsc_info_t);
-typedef struct xen_domctl_tsc_info {
- XEN_GUEST_HANDLE_64(xen_guest_tsc_info_t) out_info; /* OUT */
- xen_guest_tsc_info_t info; /* IN */
-} xen_domctl_tsc_info_t;
-
-/* XEN_DOMCTL_gdbsx_guestmemio guest mem io */
-struct xen_domctl_gdbsx_memio {
- /* IN */
- uint64_aligned_t pgd3val;/* optional: init_mm.pgd[3] value */
- uint64_aligned_t gva; /* guest virtual address */
- uint64_aligned_t uva; /* user buffer virtual address */
- uint32_t len; /* number of bytes to read/write */
- uint8_t gwr; /* 0 = read from guest. 1 = write to guest */
- /* OUT */
- uint32_t remain; /* bytes remaining to be copied */
-};
-
-/* XEN_DOMCTL_gdbsx_pausevcpu */
-/* XEN_DOMCTL_gdbsx_unpausevcpu */
-struct xen_domctl_gdbsx_pauseunp_vcpu { /* pause/unpause a vcpu */
- uint32_t vcpu; /* which vcpu */
-};
-
-/* XEN_DOMCTL_gdbsx_domstatus */
-struct xen_domctl_gdbsx_domstatus {
- /* OUT */
- uint8_t paused; /* is the domain paused */
- uint32_t vcpu_id; /* any vcpu in an event? */
- uint32_t vcpu_ev; /* if yes, what event? */
-};
-
-/*
- * Memory event operations
- */
-
-/* XEN_DOMCTL_mem_event_op */
-
-/*
- * Domain memory paging
- * Page memory in and out.
- * Domctl interface to set up and tear down the
- * pager<->hypervisor interface. Use XENMEM_paging_op*
- * to perform per-page operations.
- *
- * The XEN_DOMCTL_MEM_EVENT_OP_PAGING_ENABLE domctl returns several
- * non-standard error codes to indicate why paging could not be enabled:
- * ENODEV - host lacks HAP support (EPT/NPT) or HAP is disabled in guest
- * EMLINK - guest has iommu passthrough enabled
- * EXDEV - guest has PoD enabled
- * EBUSY - guest has or had paging enabled, ring buffer still active
- */
-#define XEN_DOMCTL_MEM_EVENT_OP_PAGING 1
-
-#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_ENABLE 0
-#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_DISABLE 1
-
-/*
- * Access permissions.
- *
- * As with paging, use the domctl for teardown/setup of the
- * helper<->hypervisor interface.
- *
- * There are HVM hypercalls to set the per-page access permissions of every
- * page in a domain. When one of these permissions--independent, read,
- * write, and execute--is violated, the VCPU is paused and a memory event
- * is sent with what happened. (See public/mem_event.h) .
- *
- * The memory event handler can then resume the VCPU and redo the access
- * with a XENMEM_access_op_resume hypercall.
- *
- * The XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE domctl returns several
- * non-standard error codes to indicate why access could not be enabled:
- * ENODEV - host lacks HAP support (EPT/NPT) or HAP is disabled in guest
- * EBUSY - guest has or had access enabled, ring buffer still active
- */
-#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS 2
-
-#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE 0
-#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_DISABLE 1
-#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE_INTROSPECTION 2
-
-/*
- * Sharing ENOMEM helper.
- *
- * As with paging, use the domctl for teardown/setup of the
- * helper<->hypervisor interface.
- *
- * If setup, this ring is used to communicate failed allocations
- * in the unshare path. XENMEM_sharing_op_resume is used to wake up
- * vcpus that could not unshare.
- *
- * Note that shring can be turned on (as per the domctl below)
- * *without* this ring being setup.
- */
-#define XEN_DOMCTL_MEM_EVENT_OP_SHARING 3
-
-#define XEN_DOMCTL_MEM_EVENT_OP_SHARING_ENABLE 0
-#define XEN_DOMCTL_MEM_EVENT_OP_SHARING_DISABLE 1
-
-/* Use for teardown/setup of helper<->hypervisor interface for paging,
- * access and sharing.*/
-struct xen_domctl_mem_event_op {
- uint32_t op; /* XEN_DOMCTL_MEM_EVENT_OP_*_* */
- uint32_t mode; /* XEN_DOMCTL_MEM_EVENT_OP_* */
-
- uint32_t port; /* OUT: event channel for ring */
-};
-typedef struct xen_domctl_mem_event_op xen_domctl_mem_event_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_mem_event_op_t);
-
-/*
- * Memory sharing operations
- */
-/* XEN_DOMCTL_mem_sharing_op.
- * The CONTROL sub-domctl is used for bringup/teardown. */
-#define XEN_DOMCTL_MEM_SHARING_CONTROL 0
-
-struct xen_domctl_mem_sharing_op {
- uint8_t op; /* XEN_DOMCTL_MEM_SHARING_* */
-
- union {
- uint8_t enable; /* CONTROL */
- } u;
-};
-typedef struct xen_domctl_mem_sharing_op xen_domctl_mem_sharing_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_mem_sharing_op_t);
-
-struct xen_domctl_audit_p2m {
- /* OUT error counts */
- uint64_t orphans;
- uint64_t m2p_bad;
- uint64_t p2m_bad;
-};
-typedef struct xen_domctl_audit_p2m xen_domctl_audit_p2m_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_audit_p2m_t);
-
-struct xen_domctl_set_virq_handler {
- uint32_t virq; /* IN */
-};
-typedef struct xen_domctl_set_virq_handler xen_domctl_set_virq_handler_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_virq_handler_t);
-
-#if defined(__i386__) || defined(__x86_64__)
-/* XEN_DOMCTL_setvcpuextstate */
-/* XEN_DOMCTL_getvcpuextstate */
-struct xen_domctl_vcpuextstate {
- /* IN: VCPU that this call applies to. */
- uint32_t vcpu;
- /*
- * SET: Ignored.
- * GET: xfeature support mask of struct (IN/OUT)
- * xfeature mask is served as identifications of the saving format
- * so that compatible CPUs can have a check on format to decide
- * whether it can restore.
- */
- uint64_aligned_t xfeature_mask;
- /*
- * SET: Size of struct (IN)
- * GET: Size of struct (IN/OUT)
- */
- uint64_aligned_t size;
- XEN_GUEST_HANDLE_64(uint64) buffer;
-};
-typedef struct xen_domctl_vcpuextstate xen_domctl_vcpuextstate_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpuextstate_t);
-#endif
-
-/* XEN_DOMCTL_set_access_required: sets whether a memory event listener
- * must be present to handle page access events: if false, the page
- * access will revert to full permissions if no one is listening;
- * */
-struct xen_domctl_set_access_required {
- uint8_t access_required;
-};
-typedef struct xen_domctl_set_access_required xen_domctl_set_access_required_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_access_required_t);
-
-struct xen_domctl_set_broken_page_p2m {
- uint64_aligned_t pfn;
-};
-typedef struct xen_domctl_set_broken_page_p2m xen_domctl_set_broken_page_p2m_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_broken_page_p2m_t);
-
-/*
- * XEN_DOMCTL_set_max_evtchn: sets the maximum event channel port
- * number the guest may use. Use this limit the amount of resources
- * (global mapping space, xenheap) a guest may use for event channels.
- */
-struct xen_domctl_set_max_evtchn {
- uint32_t max_port;
-};
-typedef struct xen_domctl_set_max_evtchn xen_domctl_set_max_evtchn_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_max_evtchn_t);
-
-/*
- * ARM: Clean and invalidate caches associated with given region of
- * guest memory.
- */
-struct xen_domctl_cacheflush {
- /* IN: page range to flush. */
- xen_pfn_t start_pfn, nr_pfns;
-};
-typedef struct xen_domctl_cacheflush xen_domctl_cacheflush_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_cacheflush_t);
-
-#if defined(__i386__) || defined(__x86_64__)
-struct xen_domctl_vcpu_msr {
- uint32_t index;
- uint32_t reserved;
- uint64_aligned_t value;
-};
-typedef struct xen_domctl_vcpu_msr xen_domctl_vcpu_msr_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpu_msr_t);
-
-/*
- * XEN_DOMCTL_set_vcpu_msrs / XEN_DOMCTL_get_vcpu_msrs.
- *
- * Input:
- * - A NULL 'msrs' guest handle is a request for the maximum 'msr_count'.
- * - Otherwise, 'msr_count' is the number of entries in 'msrs'.
- *
- * Output for get:
- * - If 'msr_count' is less than the number Xen needs to write, -ENOBUFS shall
- * be returned and 'msr_count' updated to reflect the intended number.
- * - On success, 'msr_count' shall indicate the number of MSRs written, which
- * may be less than the maximum if some are not currently used by the vcpu.
- *
- * Output for set:
- * - If Xen encounters an error with a specific MSR, -EINVAL shall be returned
- * and 'msr_count' shall be set to the offending index, to aid debugging.
- */
-struct xen_domctl_vcpu_msrs {
- uint32_t vcpu; /* IN */
- uint32_t msr_count; /* IN/OUT */
- XEN_GUEST_HANDLE_64(xen_domctl_vcpu_msr_t) msrs; /* IN/OUT */
-};
-typedef struct xen_domctl_vcpu_msrs xen_domctl_vcpu_msrs_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpu_msrs_t);
-#endif
-
-/*
- * Use in XEN_DOMCTL_setvnumainfo to set
- * vNUMA domain topology.
- */
-struct xen_domctl_vnuma {
- uint32_t nr_vnodes;
- uint32_t nr_vmemranges;
- uint32_t nr_vcpus;
- uint32_t pad;
- XEN_GUEST_HANDLE_64(uint) vdistance;
- XEN_GUEST_HANDLE_64(uint) vcpu_to_vnode;
-
- /*
- * vnodes to physical NUMA nodes mask.
- * This kept on per-domain basis for
- * interested consumers, such as numa aware ballooning.
- */
- XEN_GUEST_HANDLE_64(uint) vnode_to_pnode;
-
- /*
- * memory rages for each vNUMA node
- */
- XEN_GUEST_HANDLE_64(xen_vmemrange_t) vmemrange;
-};
-typedef struct xen_domctl_vnuma xen_domctl_vnuma_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_vnuma_t);
-
-struct xen_domctl_psr_cmt_op {
-#define XEN_DOMCTL_PSR_CMT_OP_DETACH 0
-#define XEN_DOMCTL_PSR_CMT_OP_ATTACH 1
-#define XEN_DOMCTL_PSR_CMT_OP_QUERY_RMID 2
- uint32_t cmd;
- uint32_t data;
-};
-typedef struct xen_domctl_psr_cmt_op xen_domctl_psr_cmt_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cmt_op_t);
-
-struct xen_domctl {
- uint32_t cmd;
-#define XEN_DOMCTL_createdomain 1
-#define XEN_DOMCTL_destroydomain 2
-#define XEN_DOMCTL_pausedomain 3
-#define XEN_DOMCTL_unpausedomain 4
-#define XEN_DOMCTL_getdomaininfo 5
-#define XEN_DOMCTL_getmemlist 6
-#define XEN_DOMCTL_getpageframeinfo 7
-#define XEN_DOMCTL_getpageframeinfo2 8
-#define XEN_DOMCTL_setvcpuaffinity 9
-#define XEN_DOMCTL_shadow_op 10
-#define XEN_DOMCTL_max_mem 11
-#define XEN_DOMCTL_setvcpucontext 12
-#define XEN_DOMCTL_getvcpucontext 13
-#define XEN_DOMCTL_getvcpuinfo 14
-#define XEN_DOMCTL_max_vcpus 15
-#define XEN_DOMCTL_scheduler_op 16
-#define XEN_DOMCTL_setdomainhandle 17
-#define XEN_DOMCTL_setdebugging 18
-#define XEN_DOMCTL_irq_permission 19
-#define XEN_DOMCTL_iomem_permission 20
-#define XEN_DOMCTL_ioport_permission 21
-#define XEN_DOMCTL_hypercall_init 22
-#define XEN_DOMCTL_arch_setup 23 /* Obsolete IA64 only */
-#define XEN_DOMCTL_settimeoffset 24
-#define XEN_DOMCTL_getvcpuaffinity 25
-#define XEN_DOMCTL_real_mode_area 26 /* Obsolete PPC only */
-#define XEN_DOMCTL_resumedomain 27
-#define XEN_DOMCTL_sendtrigger 28
-#define XEN_DOMCTL_subscribe 29
-#define XEN_DOMCTL_gethvmcontext 33
-#define XEN_DOMCTL_sethvmcontext 34
-#define XEN_DOMCTL_set_address_size 35
-#define XEN_DOMCTL_get_address_size 36
-#define XEN_DOMCTL_assign_device 37
-#define XEN_DOMCTL_bind_pt_irq 38
-#define XEN_DOMCTL_memory_mapping 39
-#define XEN_DOMCTL_ioport_mapping 40
-#define XEN_DOMCTL_pin_mem_cacheattr 41
-#define XEN_DOMCTL_set_ext_vcpucontext 42
-#define XEN_DOMCTL_get_ext_vcpucontext 43
-#define XEN_DOMCTL_set_opt_feature 44 /* Obsolete IA64 only */
-#define XEN_DOMCTL_test_assign_device 45
-#define XEN_DOMCTL_set_target 46
-#define XEN_DOMCTL_deassign_device 47
-#define XEN_DOMCTL_unbind_pt_irq 48
-#define XEN_DOMCTL_set_cpuid 49
-#define XEN_DOMCTL_get_device_group 50
-#define XEN_DOMCTL_set_machine_address_size 51
-#define XEN_DOMCTL_get_machine_address_size 52
-#define XEN_DOMCTL_suppress_spurious_page_faults 53
-#define XEN_DOMCTL_debug_op 54
-#define XEN_DOMCTL_gethvmcontext_partial 55
-#define XEN_DOMCTL_mem_event_op 56
-#define XEN_DOMCTL_mem_sharing_op 57
-#define XEN_DOMCTL_disable_migrate 58
-#define XEN_DOMCTL_gettscinfo 59
-#define XEN_DOMCTL_settscinfo 60
-#define XEN_DOMCTL_getpageframeinfo3 61
-#define XEN_DOMCTL_setvcpuextstate 62
-#define XEN_DOMCTL_getvcpuextstate 63
-#define XEN_DOMCTL_set_access_required 64
-#define XEN_DOMCTL_audit_p2m 65
-#define XEN_DOMCTL_set_virq_handler 66
-#define XEN_DOMCTL_set_broken_page_p2m 67
-#define XEN_DOMCTL_setnodeaffinity 68
-#define XEN_DOMCTL_getnodeaffinity 69
-#define XEN_DOMCTL_set_max_evtchn 70
-#define XEN_DOMCTL_cacheflush 71
-#define XEN_DOMCTL_get_vcpu_msrs 72
-#define XEN_DOMCTL_set_vcpu_msrs 73
-#define XEN_DOMCTL_setvnumainfo 74
-#define XEN_DOMCTL_psr_cmt_op 75
-#define XEN_DOMCTL_arm_configure_domain 76
-#define XEN_DOMCTL_gdbsx_guestmemio 1000
-#define XEN_DOMCTL_gdbsx_pausevcpu 1001
-#define XEN_DOMCTL_gdbsx_unpausevcpu 1002
-#define XEN_DOMCTL_gdbsx_domstatus 1003
- uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */
- domid_t domain;
- union {
- struct xen_domctl_createdomain createdomain;
-#if defined(__arm__) || defined(__aarch64__)
- struct xen_domctl_arm_configuredomain configuredomain;
-#endif
- struct xen_domctl_getdomaininfo getdomaininfo;
- struct xen_domctl_getmemlist getmemlist;
- struct xen_domctl_getpageframeinfo getpageframeinfo;
- struct xen_domctl_getpageframeinfo2 getpageframeinfo2;
- struct xen_domctl_getpageframeinfo3 getpageframeinfo3;
- struct xen_domctl_nodeaffinity nodeaffinity;
- struct xen_domctl_vcpuaffinity vcpuaffinity;
- struct xen_domctl_shadow_op shadow_op;
- struct xen_domctl_max_mem max_mem;
- struct xen_domctl_vcpucontext vcpucontext;
- struct xen_domctl_getvcpuinfo getvcpuinfo;
- struct xen_domctl_max_vcpus max_vcpus;
- struct xen_domctl_scheduler_op scheduler_op;
- struct xen_domctl_setdomainhandle setdomainhandle;
- struct xen_domctl_setdebugging setdebugging;
- struct xen_domctl_irq_permission irq_permission;
- struct xen_domctl_iomem_permission iomem_permission;
- struct xen_domctl_ioport_permission ioport_permission;
- struct xen_domctl_hypercall_init hypercall_init;
- struct xen_domctl_settimeoffset settimeoffset;
- struct xen_domctl_disable_migrate disable_migrate;
- struct xen_domctl_tsc_info tsc_info;
- struct xen_domctl_hvmcontext hvmcontext;
- struct xen_domctl_hvmcontext_partial hvmcontext_partial;
- struct xen_domctl_address_size address_size;
- struct xen_domctl_sendtrigger sendtrigger;
- struct xen_domctl_get_device_group get_device_group;
- struct xen_domctl_assign_device assign_device;
- struct xen_domctl_bind_pt_irq bind_pt_irq;
- struct xen_domctl_memory_mapping memory_mapping;
- struct xen_domctl_ioport_mapping ioport_mapping;
- struct xen_domctl_pin_mem_cacheattr pin_mem_cacheattr;
- struct xen_domctl_ext_vcpucontext ext_vcpucontext;
- struct xen_domctl_set_target set_target;
- struct xen_domctl_subscribe subscribe;
- struct xen_domctl_debug_op debug_op;
- struct xen_domctl_mem_event_op mem_event_op;
- struct xen_domctl_mem_sharing_op mem_sharing_op;
-#if defined(__i386__) || defined(__x86_64__)
- struct xen_domctl_cpuid cpuid;
- struct xen_domctl_vcpuextstate vcpuextstate;
- struct xen_domctl_vcpu_msrs vcpu_msrs;
-#endif
- struct xen_domctl_set_access_required access_required;
- struct xen_domctl_audit_p2m audit_p2m;
- struct xen_domctl_set_virq_handler set_virq_handler;
- struct xen_domctl_set_max_evtchn set_max_evtchn;
- struct xen_domctl_gdbsx_memio gdbsx_guest_memio;
- struct xen_domctl_set_broken_page_p2m set_broken_page_p2m;
- struct xen_domctl_cacheflush cacheflush;
- struct xen_domctl_gdbsx_pauseunp_vcpu gdbsx_pauseunp_vcpu;
- struct xen_domctl_gdbsx_domstatus gdbsx_domstatus;
- struct xen_domctl_vnuma vnuma;
- struct xen_domctl_psr_cmt_op psr_cmt_op;
- uint8_t pad[128];
- } u;
-};
-typedef struct xen_domctl xen_domctl_t;
-DEFINE_XEN_GUEST_HANDLE(xen_domctl_t);
-
-#endif /* __XEN_PUBLIC_DOMCTL_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * elfnote.h
- *
- * Definitions used for the Xen ELF notes.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2006, Ian Campbell, XenSource Ltd.
- */
-
-#ifndef __XEN_PUBLIC_ELFNOTE_H__
-#define __XEN_PUBLIC_ELFNOTE_H__
-
-/*
- * `incontents 200 elfnotes ELF notes
- *
- * The notes should live in a PT_NOTE segment and have "Xen" in the
- * name field.
- *
- * Numeric types are either 4 or 8 bytes depending on the content of
- * the desc field.
- *
- * LEGACY indicated the fields in the legacy __xen_guest string which
- * this a note type replaces.
- *
- * String values (for non-legacy) are NULL terminated ASCII, also known
- * as ASCIZ type.
- */
-
-/*
- * NAME=VALUE pair (string).
- */
-#define XEN_ELFNOTE_INFO 0
-
-/*
- * The virtual address of the entry point (numeric).
- *
- * LEGACY: VIRT_ENTRY
- */
-#define XEN_ELFNOTE_ENTRY 1
-
-/* The virtual address of the hypercall transfer page (numeric).
- *
- * LEGACY: HYPERCALL_PAGE. (n.b. legacy value is a physical page
- * number not a virtual address)
- */
-#define XEN_ELFNOTE_HYPERCALL_PAGE 2
-
-/* The virtual address where the kernel image should be mapped (numeric).
- *
- * Defaults to 0.
- *
- * LEGACY: VIRT_BASE
- */
-#define XEN_ELFNOTE_VIRT_BASE 3
-
-/*
- * The offset of the ELF paddr field from the actual required
- * pseudo-physical address (numeric).
- *
- * This is used to maintain backwards compatibility with older kernels
- * which wrote __PAGE_OFFSET into that field. This field defaults to 0
- * if not present.
- *
- * LEGACY: ELF_PADDR_OFFSET. (n.b. legacy default is VIRT_BASE)
- */
-#define XEN_ELFNOTE_PADDR_OFFSET 4
-
-/*
- * The version of Xen that we work with (string).
- *
- * LEGACY: XEN_VER
- */
-#define XEN_ELFNOTE_XEN_VERSION 5
-
-/*
- * The name of the guest operating system (string).
- *
- * LEGACY: GUEST_OS
- */
-#define XEN_ELFNOTE_GUEST_OS 6
-
-/*
- * The version of the guest operating system (string).
- *
- * LEGACY: GUEST_VER
- */
-#define XEN_ELFNOTE_GUEST_VERSION 7
-
-/*
- * The loader type (string).
- *
- * LEGACY: LOADER
- */
-#define XEN_ELFNOTE_LOADER 8
-
-/*
- * The kernel supports PAE (x86/32 only, string = "yes", "no" or
- * "bimodal").
- *
- * For compatibility with Xen 3.0.3 and earlier the "bimodal" setting
- * may be given as "yes,bimodal" which will cause older Xen to treat
- * this kernel as PAE.
- *
- * LEGACY: PAE (n.b. The legacy interface included a provision to
- * indicate 'extended-cr3' support allowing L3 page tables to be
- * placed above 4G. It is assumed that any kernel new enough to use
- * these ELF notes will include this and therefore "yes" here is
- * equivalent to "yes[entended-cr3]" in the __xen_guest interface.
- */
-#define XEN_ELFNOTE_PAE_MODE 9
-
-/*
- * The features supported/required by this kernel (string).
- *
- * The string must consist of a list of feature names (as given in
- * features.h, without the "XENFEAT_" prefix) separated by '|'
- * characters. If a feature is required for the kernel to function
- * then the feature name must be preceded by a '!' character.
- *
- * LEGACY: FEATURES
- */
-#define XEN_ELFNOTE_FEATURES 10
-
-/*
- * The kernel requires the symbol table to be loaded (string = "yes" or "no")
- * LEGACY: BSD_SYMTAB (n.b. The legacy treated the presence or absence
- * of this string as a boolean flag rather than requiring "yes" or
- * "no".
- */
-#define XEN_ELFNOTE_BSD_SYMTAB 11
-
-/*
- * The lowest address the hypervisor hole can begin at (numeric).
- *
- * This must not be set higher than HYPERVISOR_VIRT_START. Its presence
- * also indicates to the hypervisor that the kernel can deal with the
- * hole starting at a higher address.
- */
-#define XEN_ELFNOTE_HV_START_LOW 12
-
-/*
- * List of maddr_t-sized mask/value pairs describing how to recognize
- * (non-present) L1 page table entries carrying valid MFNs (numeric).
- */
-#define XEN_ELFNOTE_L1_MFN_VALID 13
-
-/*
- * Whether or not the guest supports cooperative suspend cancellation.
- * This is a numeric value.
- *
- * Default is 0
- */
-#define XEN_ELFNOTE_SUSPEND_CANCEL 14
-
-/*
- * The (non-default) location the initial phys-to-machine map should be
- * placed at by the hypervisor (Dom0) or the tools (DomU).
- * The kernel must be prepared for this mapping to be established using
- * large pages, despite such otherwise not being available to guests.
- * The kernel must also be able to handle the page table pages used for
- * this mapping not being accessible through the initial mapping.
- * (Only x86-64 supports this at present.)
- */
-#define XEN_ELFNOTE_INIT_P2M 15
-
-/*
- * Whether or not the guest can deal with being passed an initrd not
- * mapped through its initial page tables.
- */
-#define XEN_ELFNOTE_MOD_START_PFN 16
-
-/*
- * The features supported by this kernel (numeric).
- *
- * Other than XEN_ELFNOTE_FEATURES on pre-4.2 Xen, this note allows a
- * kernel to specify support for features that older hypervisors don't
- * know about. The set of features 4.2 and newer hypervisors will
- * consider supported by the kernel is the combination of the sets
- * specified through this and the string note.
- *
- * LEGACY: FEATURES
- */
-#define XEN_ELFNOTE_SUPPORTED_FEATURES 17
-
-/*
- * The number of the highest elfnote defined.
- */
-#define XEN_ELFNOTE_MAX XEN_ELFNOTE_SUPPORTED_FEATURES
-
-/*
- * System information exported through crash notes.
- *
- * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_INFO
- * note in case of a system crash. This note will contain various
- * information about the system, see xen/include/xen/elfcore.h.
- */
-#define XEN_ELFNOTE_CRASH_INFO 0x1000001
-
-/*
- * System registers exported through crash notes.
- *
- * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_REGS
- * note per cpu in case of a system crash. This note is architecture
- * specific and will contain registers not saved in the "CORE" note.
- * See xen/include/xen/elfcore.h for more information.
- */
-#define XEN_ELFNOTE_CRASH_REGS 0x1000002
-
-
-/*
- * xen dump-core none note.
- * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_NONE
- * in its dump file to indicate that the file is xen dump-core
- * file. This note doesn't have any other information.
- * See tools/libxc/xc_core.h for more information.
- */
-#define XEN_ELFNOTE_DUMPCORE_NONE 0x2000000
-
-/*
- * xen dump-core header note.
- * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_HEADER
- * in its dump file.
- * See tools/libxc/xc_core.h for more information.
- */
-#define XEN_ELFNOTE_DUMPCORE_HEADER 0x2000001
-
-/*
- * xen dump-core xen version note.
- * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_XEN_VERSION
- * in its dump file. It contains the xen version obtained via the
- * XENVER hypercall.
- * See tools/libxc/xc_core.h for more information.
- */
-#define XEN_ELFNOTE_DUMPCORE_XEN_VERSION 0x2000002
-
-/*
- * xen dump-core format version note.
- * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION
- * in its dump file. It contains a format version identifier.
- * See tools/libxc/xc_core.h for more information.
- */
-#define XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION 0x2000003
-
-#endif /* __XEN_PUBLIC_ELFNOTE_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * event_channel.h
- *
- * Event channels between domains.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2003-2004, K A Fraser.
- */
-
-#ifndef __XEN_PUBLIC_EVENT_CHANNEL_H__
-#define __XEN_PUBLIC_EVENT_CHANNEL_H__
-
-#include "xen.h"
-
-/*
- * `incontents 150 evtchn Event Channels
- *
- * Event channels are the basic primitive provided by Xen for event
- * notifications. An event is the Xen equivalent of a hardware
- * interrupt. They essentially store one bit of information, the event
- * of interest is signalled by transitioning this bit from 0 to 1.
- *
- * Notifications are received by a guest via an upcall from Xen,
- * indicating when an event arrives (setting the bit). Further
- * notifications are masked until the bit is cleared again (therefore,
- * guests must check the value of the bit after re-enabling event
- * delivery to ensure no missed notifications).
- *
- * Event notifications can be masked by setting a flag; this is
- * equivalent to disabling interrupts and can be used to ensure
- * atomicity of certain operations in the guest kernel.
- *
- * Event channels are represented by the evtchn_* fields in
- * struct shared_info and struct vcpu_info.
- */
-
-/*
- * ` enum neg_errnoval
- * ` HYPERVISOR_event_channel_op(enum event_channel_op cmd, void *args)
- * `
- * @cmd == EVTCHNOP_* (event-channel operation).
- * @args == struct evtchn_* Operation-specific extra arguments (NULL if none).
- */
-
-/* ` enum event_channel_op { // EVTCHNOP_* => struct evtchn_* */
-#define EVTCHNOP_bind_interdomain 0
-#define EVTCHNOP_bind_virq 1
-#define EVTCHNOP_bind_pirq 2
-#define EVTCHNOP_close 3
-#define EVTCHNOP_send 4
-#define EVTCHNOP_status 5
-#define EVTCHNOP_alloc_unbound 6
-#define EVTCHNOP_bind_ipi 7
-#define EVTCHNOP_bind_vcpu 8
-#define EVTCHNOP_unmask 9
-#define EVTCHNOP_reset 10
-#define EVTCHNOP_init_control 11
-#define EVTCHNOP_expand_array 12
-#define EVTCHNOP_set_priority 13
-/* ` } */
-
-typedef uint32_t evtchn_port_t;
-DEFINE_XEN_GUEST_HANDLE(evtchn_port_t);
-
-/*
- * EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as
- * accepting interdomain bindings from domain <remote_dom>. A fresh port
- * is allocated in <dom> and returned as <port>.
- * NOTES:
- * 1. If the caller is unprivileged then <dom> must be DOMID_SELF.
- * 2. <rdom> may be DOMID_SELF, allowing loopback connections.
- */
-struct evtchn_alloc_unbound {
- /* IN parameters */
- domid_t dom, remote_dom;
- /* OUT parameters */
- evtchn_port_t port;
-};
-typedef struct evtchn_alloc_unbound evtchn_alloc_unbound_t;
-
-/*
- * EVTCHNOP_bind_interdomain: Construct an interdomain event channel between
- * the calling domain and <remote_dom>. <remote_dom,remote_port> must identify
- * a port that is unbound and marked as accepting bindings from the calling
- * domain. A fresh port is allocated in the calling domain and returned as
- * <local_port>.
- *
- * In case the peer domain has already tried to set our event channel
- * pending, before it was bound, EVTCHNOP_bind_interdomain always sets
- * the local event channel pending.
- *
- * The usual pattern of use, in the guest's upcall (or subsequent
- * handler) is as follows: (Re-enable the event channel for subsequent
- * signalling and then) check for the existence of whatever condition
- * is being waited for by other means, and take whatever action is
- * needed (if any).
- *
- * NOTES:
- * 1. <remote_dom> may be DOMID_SELF, allowing loopback connections.
- */
-struct evtchn_bind_interdomain {
- /* IN parameters. */
- domid_t remote_dom;
- evtchn_port_t remote_port;
- /* OUT parameters. */
- evtchn_port_t local_port;
-};
-typedef struct evtchn_bind_interdomain evtchn_bind_interdomain_t;
-
-/*
- * EVTCHNOP_bind_virq: Bind a local event channel to VIRQ <irq> on specified
- * vcpu.
- * NOTES:
- * 1. Virtual IRQs are classified as per-vcpu or global. See the VIRQ list
- * in xen.h for the classification of each VIRQ.
- * 2. Global VIRQs must be allocated on VCPU0 but can subsequently be
- * re-bound via EVTCHNOP_bind_vcpu.
- * 3. Per-vcpu VIRQs may be bound to at most one event channel per vcpu.
- * The allocated event channel is bound to the specified vcpu and the
- * binding cannot be changed.
- */
-struct evtchn_bind_virq {
- /* IN parameters. */
- uint32_t virq; /* enum virq */
- uint32_t vcpu;
- /* OUT parameters. */
- evtchn_port_t port;
-};
-typedef struct evtchn_bind_virq evtchn_bind_virq_t;
-
-/*
- * EVTCHNOP_bind_pirq: Bind a local event channel to a real IRQ (PIRQ <irq>).
- * NOTES:
- * 1. A physical IRQ may be bound to at most one event channel per domain.
- * 2. Only a sufficiently-privileged domain may bind to a physical IRQ.
- */
-struct evtchn_bind_pirq {
- /* IN parameters. */
- uint32_t pirq;
-#define BIND_PIRQ__WILL_SHARE 1
- uint32_t flags; /* BIND_PIRQ__* */
- /* OUT parameters. */
- evtchn_port_t port;
-};
-typedef struct evtchn_bind_pirq evtchn_bind_pirq_t;
-
-/*
- * EVTCHNOP_bind_ipi: Bind a local event channel to receive events.
- * NOTES:
- * 1. The allocated event channel is bound to the specified vcpu. The binding
- * may not be changed.
- */
-struct evtchn_bind_ipi {
- uint32_t vcpu;
- /* OUT parameters. */
- evtchn_port_t port;
-};
-typedef struct evtchn_bind_ipi evtchn_bind_ipi_t;
-
-/*
- * EVTCHNOP_close: Close a local event channel <port>. If the channel is
- * interdomain then the remote end is placed in the unbound state
- * (EVTCHNSTAT_unbound), awaiting a new connection.
- */
-struct evtchn_close {
- /* IN parameters. */
- evtchn_port_t port;
-};
-typedef struct evtchn_close evtchn_close_t;
-
-/*
- * EVTCHNOP_send: Send an event to the remote end of the channel whose local
- * endpoint is <port>.
- */
-struct evtchn_send {
- /* IN parameters. */
- evtchn_port_t port;
-};
-typedef struct evtchn_send evtchn_send_t;
-
-/*
- * EVTCHNOP_status: Get the current status of the communication channel which
- * has an endpoint at <dom, port>.
- * NOTES:
- * 1. <dom> may be specified as DOMID_SELF.
- * 2. Only a sufficiently-privileged domain may obtain the status of an event
- * channel for which <dom> is not DOMID_SELF.
- */
-struct evtchn_status {
- /* IN parameters */
- domid_t dom;
- evtchn_port_t port;
- /* OUT parameters */
-#define EVTCHNSTAT_closed 0 /* Channel is not in use. */
-#define EVTCHNSTAT_unbound 1 /* Channel is waiting interdom connection.*/
-#define EVTCHNSTAT_interdomain 2 /* Channel is connected to remote domain. */
-#define EVTCHNSTAT_pirq 3 /* Channel is bound to a phys IRQ line. */
-#define EVTCHNSTAT_virq 4 /* Channel is bound to a virtual IRQ line */
-#define EVTCHNSTAT_ipi 5 /* Channel is bound to a virtual IPI line */
- uint32_t status;
- uint32_t vcpu; /* VCPU to which this channel is bound. */
- union {
- struct {
- domid_t dom;
- } unbound; /* EVTCHNSTAT_unbound */
- struct {
- domid_t dom;
- evtchn_port_t port;
- } interdomain; /* EVTCHNSTAT_interdomain */
- uint32_t pirq; /* EVTCHNSTAT_pirq */
- uint32_t virq; /* EVTCHNSTAT_virq */
- } u;
-};
-typedef struct evtchn_status evtchn_status_t;
-
-/*
- * EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an
- * event is pending.
- * NOTES:
- * 1. IPI-bound channels always notify the vcpu specified at bind time.
- * This binding cannot be changed.
- * 2. Per-VCPU VIRQ channels always notify the vcpu specified at bind time.
- * This binding cannot be changed.
- * 3. All other channels notify vcpu0 by default. This default is set when
- * the channel is allocated (a port that is freed and subsequently reused
- * has its binding reset to vcpu0).
- */
-struct evtchn_bind_vcpu {
- /* IN parameters. */
- evtchn_port_t port;
- uint32_t vcpu;
-};
-typedef struct evtchn_bind_vcpu evtchn_bind_vcpu_t;
-
-/*
- * EVTCHNOP_unmask: Unmask the specified local event-channel port and deliver
- * a notification to the appropriate VCPU if an event is pending.
- */
-struct evtchn_unmask {
- /* IN parameters. */
- evtchn_port_t port;
-};
-typedef struct evtchn_unmask evtchn_unmask_t;
-
-/*
- * EVTCHNOP_reset: Close all event channels associated with specified domain.
- * NOTES:
- * 1. <dom> may be specified as DOMID_SELF.
- * 2. Only a sufficiently-privileged domain may specify other than DOMID_SELF.
- * 3. Destroys all control blocks and event array, resets event channel
- * operations to 2-level ABI if called with <dom> == DOMID_SELF and FIFO
- * ABI was used. Guests should not bind events during EVTCHNOP_reset call
- * as these events are likely to be lost.
- */
-struct evtchn_reset {
- /* IN parameters. */
- domid_t dom;
-};
-typedef struct evtchn_reset evtchn_reset_t;
-
-/*
- * EVTCHNOP_init_control: initialize the control block for the FIFO ABI.
- *
- * Note: any events that are currently pending will not be resent and
- * will be lost. Guests should call this before binding any event to
- * avoid losing any events.
- */
-struct evtchn_init_control {
- /* IN parameters. */
- uint64_t control_gfn;
- uint32_t offset;
- uint32_t vcpu;
- /* OUT parameters. */
- uint8_t link_bits;
- uint8_t _pad[7];
-};
-typedef struct evtchn_init_control evtchn_init_control_t;
-
-/*
- * EVTCHNOP_expand_array: add an additional page to the event array.
- */
-struct evtchn_expand_array {
- /* IN parameters. */
- uint64_t array_gfn;
-};
-typedef struct evtchn_expand_array evtchn_expand_array_t;
-
-/*
- * EVTCHNOP_set_priority: set the priority for an event channel.
- */
-struct evtchn_set_priority {
- /* IN parameters. */
- uint32_t port;
- uint32_t priority;
-};
-typedef struct evtchn_set_priority evtchn_set_priority_t;
-
-/*
- * ` enum neg_errnoval
- * ` HYPERVISOR_event_channel_op_compat(struct evtchn_op *op)
- * `
- * Superceded by new event_channel_op() hypercall since 0x00030202.
- */
-struct evtchn_op {
- uint32_t cmd; /* enum event_channel_op */
- union {
- struct evtchn_alloc_unbound alloc_unbound;
- struct evtchn_bind_interdomain bind_interdomain;
- struct evtchn_bind_virq bind_virq;
- struct evtchn_bind_pirq bind_pirq;
- struct evtchn_bind_ipi bind_ipi;
- struct evtchn_close close;
- struct evtchn_send send;
- struct evtchn_status status;
- struct evtchn_bind_vcpu bind_vcpu;
- struct evtchn_unmask unmask;
- } u;
-};
-typedef struct evtchn_op evtchn_op_t;
-DEFINE_XEN_GUEST_HANDLE(evtchn_op_t);
-
-/*
- * 2-level ABI
- */
-
-#define EVTCHN_2L_NR_CHANNELS (sizeof(xen_ulong_t) * sizeof(xen_ulong_t) * 64)
-
-/*
- * FIFO ABI
- */
-
-/* Events may have priorities from 0 (highest) to 15 (lowest). */
-#define EVTCHN_FIFO_PRIORITY_MAX 0
-#define EVTCHN_FIFO_PRIORITY_DEFAULT 7
-#define EVTCHN_FIFO_PRIORITY_MIN 15
-
-#define EVTCHN_FIFO_MAX_QUEUES (EVTCHN_FIFO_PRIORITY_MIN + 1)
-
-typedef uint32_t event_word_t;
-
-#define EVTCHN_FIFO_PENDING 31
-#define EVTCHN_FIFO_MASKED 30
-#define EVTCHN_FIFO_LINKED 29
-#define EVTCHN_FIFO_BUSY 28
-
-#define EVTCHN_FIFO_LINK_BITS 17
-#define EVTCHN_FIFO_LINK_MASK ((1 << EVTCHN_FIFO_LINK_BITS) - 1)
-
-#define EVTCHN_FIFO_NR_CHANNELS (1 << EVTCHN_FIFO_LINK_BITS)
-
-struct evtchn_fifo_control_block {
- uint32_t ready;
- uint32_t _rsvd;
- uint32_t head[EVTCHN_FIFO_MAX_QUEUES];
-};
-typedef struct evtchn_fifo_control_block evtchn_fifo_control_block_t;
-
-#endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * features.h
- *
- * Feature flags, reported by XENVER_get_features.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2006, Keir Fraser <keir@xensource.com>
- */
-
-#ifndef __XEN_PUBLIC_FEATURES_H__
-#define __XEN_PUBLIC_FEATURES_H__
-
-/*
- * `incontents 200 elfnotes_features XEN_ELFNOTE_FEATURES
- *
- * The list of all the features the guest supports. They are set by
- * parsing the XEN_ELFNOTE_FEATURES and XEN_ELFNOTE_SUPPORTED_FEATURES
- * string. The format is the feature names (as given here without the
- * "XENFEAT_" prefix) separated by '|' characters.
- * If a feature is required for the kernel to function then the feature name
- * must be preceded by a '!' character.
- *
- * Note that if XEN_ELFNOTE_SUPPORTED_FEATURES is used, then in the
- * XENFEAT_dom0 MUST be set if the guest is to be booted as dom0,
- */
-
-/*
- * If set, the guest does not need to write-protect its pagetables, and can
- * update them via direct writes.
- */
-#define XENFEAT_writable_page_tables 0
-
-/*
- * If set, the guest does not need to write-protect its segment descriptor
- * tables, and can update them via direct writes.
- */
-#define XENFEAT_writable_descriptor_tables 1
-
-/*
- * If set, translation between the guest's 'pseudo-physical' address space
- * and the host's machine address space are handled by the hypervisor. In this
- * mode the guest does not need to perform phys-to/from-machine translations
- * when performing page table operations.
- */
-#define XENFEAT_auto_translated_physmap 2
-
-/* If set, the guest is running in supervisor mode (e.g., x86 ring 0). */
-#define XENFEAT_supervisor_mode_kernel 3
-
-/*
- * If set, the guest does not need to allocate x86 PAE page directories
- * below 4GB. This flag is usually implied by auto_translated_physmap.
- */
-#define XENFEAT_pae_pgdir_above_4gb 4
-
-/* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */
-#define XENFEAT_mmu_pt_update_preserve_ad 5
-
-/* x86: Does this Xen host support the MMU_{CLEAR,COPY}_PAGE hypercall? */
-#define XENFEAT_highmem_assist 6
-
-/*
- * If set, GNTTABOP_map_grant_ref honors flags to be placed into guest kernel
- * available pte bits.
- */
-#define XENFEAT_gnttab_map_avail_bits 7
-
-/* x86: Does this Xen host support the HVM callback vector type? */
-#define XENFEAT_hvm_callback_vector 8
-
-/* x86: pvclock algorithm is safe to use on HVM */
-#define XENFEAT_hvm_safe_pvclock 9
-
-/* x86: pirq can be used by HVM guests */
-#define XENFEAT_hvm_pirqs 10
-
-/* operation as Dom0 is supported */
-#define XENFEAT_dom0 11
-
-/* Xen also maps grant references at pfn = mfn.
- * This feature flag is deprecated and should not be used.
-#define XENFEAT_grant_map_identity 12
- */
-
-#define XENFEAT_NR_SUBMAPS 1
-
-#endif /* __XEN_PUBLIC_FEATURES_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * gcov.h
- *
- * Coverage structures exported by Xen.
- * Structure is different from Gcc one.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2013, Citrix Systems R&D Ltd.
- */
-
-#ifndef __XEN_PUBLIC_GCOV_H__
-#define __XEN_PUBLIC_GCOV_H__ __XEN_PUBLIC_GCOV_H__
-
-#define XENCOV_COUNTERS 5
-#define XENCOV_TAG_BASE 0x58544300u
-#define XENCOV_TAG_FILE (XENCOV_TAG_BASE+0x46u)
-#define XENCOV_TAG_FUNC (XENCOV_TAG_BASE+0x66u)
-#define XENCOV_TAG_COUNTER(n) (XENCOV_TAG_BASE+0x30u+((n)&0xfu))
-#define XENCOV_TAG_END (XENCOV_TAG_BASE+0x2eu)
-#define XENCOV_IS_TAG_COUNTER(n) \
- ((n) >= XENCOV_TAG_COUNTER(0) && (n) < XENCOV_TAG_COUNTER(XENCOV_COUNTERS))
-#define XENCOV_COUNTER_NUM(n) ((n)-XENCOV_TAG_COUNTER(0))
-
-/*
- * The main structure for the blob is
- * BLOB := FILE.. END
- * FILE := TAG_FILE VERSION STAMP FILENAME COUNTERS FUNCTIONS
- * FILENAME := LEN characters
- * characters are padded to 32 bit
- * LEN := 32 bit value
- * COUNTERS := TAG_COUNTER(n) NUM COUNTER..
- * NUM := 32 bit valie
- * COUNTER := 64 bit value
- * FUNCTIONS := TAG_FUNC NUM FUNCTION..
- * FUNCTION := IDENT CHECKSUM NUM_COUNTERS
- *
- * All tagged structures are aligned to 8 bytes
- */
-
-/**
- * File information
- * Prefixed with XENCOV_TAG_FILE and a string with filename
- * Aligned to 8 bytes
- */
-struct xencov_file
-{
- uint32_t tag; /* XENCOV_TAG_FILE */
- uint32_t version;
- uint32_t stamp;
- uint32_t fn_len;
- char filename[1];
-};
-
-
-/**
- * Counters information
- * Prefixed with XENCOV_TAG_COUNTER(n) where n is 0..(XENCOV_COUNTERS-1)
- * Aligned to 8 bytes
- */
-struct xencov_counter
-{
- uint32_t tag; /* XENCOV_TAG_COUNTER(n) */
- uint32_t num;
- uint64_t values[1];
-};
-
-/**
- * Information for each function
- * Number of counter is equal to the number of counter structures got before
- */
-struct xencov_function
-{
- uint32_t ident;
- uint32_t checksum;
- uint32_t num_counters[1];
-};
-
-/**
- * Information for all functions
- * Aligned to 8 bytes
- */
-struct xencov_functions
-{
- uint32_t tag; /* XENCOV_TAG_FUNC */
- uint32_t num;
- struct xencov_function xencov_function[1];
-};
-
-/**
- * Terminator
- */
-struct xencov_end
-{
- uint32_t tag; /* XENCOV_TAG_END */
-};
-
-#endif /* __XEN_PUBLIC_GCOV_H__ */
-
+++ /dev/null
-/******************************************************************************
- * grant_table.h
- *
- * Interface for granting foreign access to page frames, and receiving
- * page-ownership transfers.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2004, K A Fraser
- */
-
-#ifndef __XEN_PUBLIC_GRANT_TABLE_H__
-#define __XEN_PUBLIC_GRANT_TABLE_H__
-
-#include "xen.h"
-
-/*
- * `incontents 150 gnttab Grant Tables
- *
- * Xen's grant tables provide a generic mechanism to memory sharing
- * between domains. This shared memory interface underpins the split
- * device drivers for block and network IO.
- *
- * Each domain has its own grant table. This is a data structure that
- * is shared with Xen; it allows the domain to tell Xen what kind of
- * permissions other domains have on its pages. Entries in the grant
- * table are identified by grant references. A grant reference is an
- * integer, which indexes into the grant table. It acts as a
- * capability which the grantee can use to perform operations on the
- * granter’s memory.
- *
- * This capability-based system allows shared-memory communications
- * between unprivileged domains. A grant reference also encapsulates
- * the details of a shared page, removing the need for a domain to
- * know the real machine address of a page it is sharing. This makes
- * it possible to share memory correctly with domains running in
- * fully virtualised memory.
- */
-
-/***********************************
- * GRANT TABLE REPRESENTATION
- */
-
-/* Some rough guidelines on accessing and updating grant-table entries
- * in a concurrency-safe manner. For more information, Linux contains a
- * reference implementation for guest OSes (drivers/xen/grant_table.c, see
- * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/xen/grant-table.c;hb=HEAD
- *
- * NB. WMB is a no-op on current-generation x86 processors. However, a
- * compiler barrier will still be required.
- *
- * Introducing a valid entry into the grant table:
- * 1. Write ent->domid.
- * 2. Write ent->frame:
- * GTF_permit_access: Frame to which access is permitted.
- * GTF_accept_transfer: Pseudo-phys frame slot being filled by new
- * frame, or zero if none.
- * 3. Write memory barrier (WMB).
- * 4. Write ent->flags, inc. valid type.
- *
- * Invalidating an unused GTF_permit_access entry:
- * 1. flags = ent->flags.
- * 2. Observe that !(flags & (GTF_reading|GTF_writing)).
- * 3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
- * NB. No need for WMB as reuse of entry is control-dependent on success of
- * step 3, and all architectures guarantee ordering of ctrl-dep writes.
- *
- * Invalidating an in-use GTF_permit_access entry:
- * This cannot be done directly. Request assistance from the domain controller
- * which can set a timeout on the use of a grant entry and take necessary
- * action. (NB. This is not yet implemented!).
- *
- * Invalidating an unused GTF_accept_transfer entry:
- * 1. flags = ent->flags.
- * 2. Observe that !(flags & GTF_transfer_committed). [*]
- * 3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
- * NB. No need for WMB as reuse of entry is control-dependent on success of
- * step 3, and all architectures guarantee ordering of ctrl-dep writes.
- * [*] If GTF_transfer_committed is set then the grant entry is 'committed'.
- * The guest must /not/ modify the grant entry until the address of the
- * transferred frame is written. It is safe for the guest to spin waiting
- * for this to occur (detect by observing GTF_transfer_completed in
- * ent->flags).
- *
- * Invalidating a committed GTF_accept_transfer entry:
- * 1. Wait for (ent->flags & GTF_transfer_completed).
- *
- * Changing a GTF_permit_access from writable to read-only:
- * Use SMP-safe CMPXCHG to set GTF_readonly, while checking !GTF_writing.
- *
- * Changing a GTF_permit_access from read-only to writable:
- * Use SMP-safe bit-setting instruction.
- */
-
-/*
- * Reference to a grant entry in a specified domain's grant table.
- */
-typedef uint32_t grant_ref_t;
-
-/*
- * A grant table comprises a packed array of grant entries in one or more
- * page frames shared between Xen and a guest.
- * [XEN]: This field is written by Xen and read by the sharing guest.
- * [GST]: This field is written by the guest and read by Xen.
- */
-
-/*
- * Version 1 of the grant table entry structure is maintained purely
- * for backwards compatibility. New guests should use version 2.
- */
-#if __XEN_INTERFACE_VERSION__ < 0x0003020a
-#define grant_entry_v1 grant_entry
-#define grant_entry_v1_t grant_entry_t
-#endif
-struct grant_entry_v1 {
- /* GTF_xxx: various type and flag information. [XEN,GST] */
- uint16_t flags;
- /* The domain being granted foreign privileges. [GST] */
- domid_t domid;
- /*
- * GTF_permit_access: Frame that @domid is allowed to map and access. [GST]
- * GTF_accept_transfer: Frame whose ownership transferred by @domid. [XEN]
- */
- uint32_t frame;
-};
-typedef struct grant_entry_v1 grant_entry_v1_t;
-
-/* The first few grant table entries will be preserved across grant table
- * version changes and may be pre-populated at domain creation by tools.
- */
-#define GNTTAB_NR_RESERVED_ENTRIES 8
-#define GNTTAB_RESERVED_CONSOLE 0
-#define GNTTAB_RESERVED_XENSTORE 1
-
-/*
- * Type of grant entry.
- * GTF_invalid: This grant entry grants no privileges.
- * GTF_permit_access: Allow @domid to map/access @frame.
- * GTF_accept_transfer: Allow @domid to transfer ownership of one page frame
- * to this guest. Xen writes the page number to @frame.
- * GTF_transitive: Allow @domid to transitively access a subrange of
- * @trans_grant in @trans_domid. No mappings are allowed.
- */
-#define GTF_invalid (0U<<0)
-#define GTF_permit_access (1U<<0)
-#define GTF_accept_transfer (2U<<0)
-#define GTF_transitive (3U<<0)
-#define GTF_type_mask (3U<<0)
-
-/*
- * Subflags for GTF_permit_access.
- * GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST]
- * GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN]
- * GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN]
- * GTF_PAT, GTF_PWT, GTF_PCD: (x86) cache attribute flags for the grant [GST]
- * GTF_sub_page: Grant access to only a subrange of the page. @domid
- * will only be allowed to copy from the grant, and not
- * map it. [GST]
- */
-#define _GTF_readonly (2)
-#define GTF_readonly (1U<<_GTF_readonly)
-#define _GTF_reading (3)
-#define GTF_reading (1U<<_GTF_reading)
-#define _GTF_writing (4)
-#define GTF_writing (1U<<_GTF_writing)
-#define _GTF_PWT (5)
-#define GTF_PWT (1U<<_GTF_PWT)
-#define _GTF_PCD (6)
-#define GTF_PCD (1U<<_GTF_PCD)
-#define _GTF_PAT (7)
-#define GTF_PAT (1U<<_GTF_PAT)
-#define _GTF_sub_page (8)
-#define GTF_sub_page (1U<<_GTF_sub_page)
-
-/*
- * Subflags for GTF_accept_transfer:
- * GTF_transfer_committed: Xen sets this flag to indicate that it is committed
- * to transferring ownership of a page frame. When a guest sees this flag
- * it must /not/ modify the grant entry until GTF_transfer_completed is
- * set by Xen.
- * GTF_transfer_completed: It is safe for the guest to spin-wait on this flag
- * after reading GTF_transfer_committed. Xen will always write the frame
- * address, followed by ORing this flag, in a timely manner.
- */
-#define _GTF_transfer_committed (2)
-#define GTF_transfer_committed (1U<<_GTF_transfer_committed)
-#define _GTF_transfer_completed (3)
-#define GTF_transfer_completed (1U<<_GTF_transfer_completed)
-
-/*
- * Version 2 grant table entries. These fulfil the same role as
- * version 1 entries, but can represent more complicated operations.
- * Any given domain will have either a version 1 or a version 2 table,
- * and every entry in the table will be the same version.
- *
- * The interface by which domains use grant references does not depend
- * on the grant table version in use by the other domain.
- */
-#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
-/*
- * Version 1 and version 2 grant entries share a common prefix. The
- * fields of the prefix are documented as part of struct
- * grant_entry_v1.
- */
-struct grant_entry_header {
- uint16_t flags;
- domid_t domid;
-};
-typedef struct grant_entry_header grant_entry_header_t;
-
-/*
- * Version 2 of the grant entry structure.
- */
-union grant_entry_v2 {
- grant_entry_header_t hdr;
-
- /*
- * This member is used for V1-style full page grants, where either:
- *
- * -- hdr.type is GTF_accept_transfer, or
- * -- hdr.type is GTF_permit_access and GTF_sub_page is not set.
- *
- * In that case, the frame field has the same semantics as the
- * field of the same name in the V1 entry structure.
- */
- struct {
- grant_entry_header_t hdr;
- uint32_t pad0;
- uint64_t frame;
- } full_page;
-
- /*
- * If the grant type is GTF_grant_access and GTF_sub_page is set,
- * @domid is allowed to access bytes [@page_off,@page_off+@length)
- * in frame @frame.
- */
- struct {
- grant_entry_header_t hdr;
- uint16_t page_off;
- uint16_t length;
- uint64_t frame;
- } sub_page;
-
- /*
- * If the grant is GTF_transitive, @domid is allowed to use the
- * grant @gref in domain @trans_domid, as if it was the local
- * domain. Obviously, the transitive access must be compatible
- * with the original grant.
- *
- * The current version of Xen does not allow transitive grants
- * to be mapped.
- */
- struct {
- grant_entry_header_t hdr;
- domid_t trans_domid;
- uint16_t pad0;
- grant_ref_t gref;
- } transitive;
-
- uint32_t __spacer[4]; /* Pad to a power of two */
-};
-typedef union grant_entry_v2 grant_entry_v2_t;
-
-typedef uint16_t grant_status_t;
-
-#endif /* __XEN_INTERFACE_VERSION__ */
-
-/***********************************
- * GRANT TABLE QUERIES AND USES
- */
-
-/* ` enum neg_errnoval
- * ` HYPERVISOR_grant_table_op(enum grant_table_op cmd,
- * ` void *args,
- * ` unsigned int count)
- * `
- *
- * @args points to an array of a per-command data structure. The array
- * has @count members
- */
-
-/* ` enum grant_table_op { // GNTTABOP_* => struct gnttab_* */
-#define GNTTABOP_map_grant_ref 0
-#define GNTTABOP_unmap_grant_ref 1
-#define GNTTABOP_setup_table 2
-#define GNTTABOP_dump_table 3
-#define GNTTABOP_transfer 4
-#define GNTTABOP_copy 5
-#define GNTTABOP_query_size 6
-#define GNTTABOP_unmap_and_replace 7
-#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
-#define GNTTABOP_set_version 8
-#define GNTTABOP_get_status_frames 9
-#define GNTTABOP_get_version 10
-#define GNTTABOP_swap_grant_ref 11
-#define GNTTABOP_cache_flush 12
-#endif /* __XEN_INTERFACE_VERSION__ */
-/* ` } */
-
-/*
- * Handle to track a mapping created via a grant reference.
- */
-typedef uint32_t grant_handle_t;
-
-/*
- * GNTTABOP_map_grant_ref: Map the grant entry (<dom>,<ref>) for access
- * by devices and/or host CPUs. If successful, <handle> is a tracking number
- * that must be presented later to destroy the mapping(s). On error, <handle>
- * is a negative status code.
- * NOTES:
- * 1. If GNTMAP_device_map is specified then <dev_bus_addr> is the address
- * via which I/O devices may access the granted frame.
- * 2. If GNTMAP_host_map is specified then a mapping will be added at
- * either a host virtual address in the current address space, or at
- * a PTE at the specified machine address. The type of mapping to
- * perform is selected through the GNTMAP_contains_pte flag, and the
- * address is specified in <host_addr>.
- * 3. Mappings should only be destroyed via GNTTABOP_unmap_grant_ref. If a
- * host mapping is destroyed by other means then it is *NOT* guaranteed
- * to be accounted to the correct grant reference!
- */
-struct gnttab_map_grant_ref {
- /* IN parameters. */
- uint64_t host_addr;
- uint32_t flags; /* GNTMAP_* */
- grant_ref_t ref;
- domid_t dom;
- /* OUT parameters. */
- int16_t status; /* => enum grant_status */
- grant_handle_t handle;
- uint64_t dev_bus_addr;
-};
-typedef struct gnttab_map_grant_ref gnttab_map_grant_ref_t;
-DEFINE_XEN_GUEST_HANDLE(gnttab_map_grant_ref_t);
-
-/*
- * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
- * tracked by <handle>. If <host_addr> or <dev_bus_addr> is zero, that
- * field is ignored. If non-zero, they must refer to a device/host mapping
- * that is tracked by <handle>
- * NOTES:
- * 1. The call may fail in an undefined manner if either mapping is not
- * tracked by <handle>.
- * 3. After executing a batch of unmaps, it is guaranteed that no stale
- * mappings will remain in the device or host TLBs.
- */
-struct gnttab_unmap_grant_ref {
- /* IN parameters. */
- uint64_t host_addr;
- uint64_t dev_bus_addr;
- grant_handle_t handle;
- /* OUT parameters. */
- int16_t status; /* => enum grant_status */
-};
-typedef struct gnttab_unmap_grant_ref gnttab_unmap_grant_ref_t;
-DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_grant_ref_t);
-
-/*
- * GNTTABOP_setup_table: Set up a grant table for <dom> comprising at least
- * <nr_frames> pages. The frame addresses are written to the <frame_list>.
- * Only <nr_frames> addresses are written, even if the table is larger.
- * NOTES:
- * 1. <dom> may be specified as DOMID_SELF.
- * 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
- * 3. Xen may not support more than a single grant-table page per domain.
- */
-struct gnttab_setup_table {
- /* IN parameters. */
- domid_t dom;
- uint32_t nr_frames;
- /* OUT parameters. */
- int16_t status; /* => enum grant_status */
-#if __XEN_INTERFACE_VERSION__ < 0x00040300
- XEN_GUEST_HANDLE(ulong) frame_list;
-#else
- XEN_GUEST_HANDLE(xen_pfn_t) frame_list;
-#endif
-};
-typedef struct gnttab_setup_table gnttab_setup_table_t;
-DEFINE_XEN_GUEST_HANDLE(gnttab_setup_table_t);
-
-/*
- * GNTTABOP_dump_table: Dump the contents of the grant table to the
- * xen console. Debugging use only.
- */
-struct gnttab_dump_table {
- /* IN parameters. */
- domid_t dom;
- /* OUT parameters. */
- int16_t status; /* => enum grant_status */
-};
-typedef struct gnttab_dump_table gnttab_dump_table_t;
-DEFINE_XEN_GUEST_HANDLE(gnttab_dump_table_t);
-
-/*
- * GNTTABOP_transfer_grant_ref: Transfer <frame> to a foreign domain. The
- * foreign domain has previously registered its interest in the transfer via
- * <domid, ref>.
- *
- * Note that, even if the transfer fails, the specified page no longer belongs
- * to the calling domain *unless* the error is GNTST_bad_page.
- */
-struct gnttab_transfer {
- /* IN parameters. */
- xen_pfn_t mfn;
- domid_t domid;
- grant_ref_t ref;
- /* OUT parameters. */
- int16_t status;
-};
-typedef struct gnttab_transfer gnttab_transfer_t;
-DEFINE_XEN_GUEST_HANDLE(gnttab_transfer_t);
-
-
-/*
- * GNTTABOP_copy: Hypervisor based copy
- * source and destinations can be eithers MFNs or, for foreign domains,
- * grant references. the foreign domain has to grant read/write access
- * in its grant table.
- *
- * The flags specify what type source and destinations are (either MFN
- * or grant reference).
- *
- * Note that this can also be used to copy data between two domains
- * via a third party if the source and destination domains had previously
- * grant appropriate access to their pages to the third party.
- *
- * source_offset specifies an offset in the source frame, dest_offset
- * the offset in the target frame and len specifies the number of
- * bytes to be copied.
- */
-
-#define _GNTCOPY_source_gref (0)
-#define GNTCOPY_source_gref (1<<_GNTCOPY_source_gref)
-#define _GNTCOPY_dest_gref (1)
-#define GNTCOPY_dest_gref (1<<_GNTCOPY_dest_gref)
-
-struct gnttab_copy {
- /* IN parameters. */
- struct {
- union {
- grant_ref_t ref;
- xen_pfn_t gmfn;
- } u;
- domid_t domid;
- uint16_t offset;
- } source, dest;
- uint16_t len;
- uint16_t flags; /* GNTCOPY_* */
- /* OUT parameters. */
- int16_t status;
-};
-typedef struct gnttab_copy gnttab_copy_t;
-DEFINE_XEN_GUEST_HANDLE(gnttab_copy_t);
-
-/*
- * GNTTABOP_query_size: Query the current and maximum sizes of the shared
- * grant table.
- * NOTES:
- * 1. <dom> may be specified as DOMID_SELF.
- * 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
- */
-struct gnttab_query_size {
- /* IN parameters. */
- domid_t dom;
- /* OUT parameters. */
- uint32_t nr_frames;
- uint32_t max_nr_frames;
- int16_t status; /* => enum grant_status */
-};
-typedef struct gnttab_query_size gnttab_query_size_t;
-DEFINE_XEN_GUEST_HANDLE(gnttab_query_size_t);
-
-/*
- * GNTTABOP_unmap_and_replace: Destroy one or more grant-reference mappings
- * tracked by <handle> but atomically replace the page table entry with one
- * pointing to the machine address under <new_addr>. <new_addr> will be
- * redirected to the null entry.
- * NOTES:
- * 1. The call may fail in an undefined manner if either mapping is not
- * tracked by <handle>.
- * 2. After executing a batch of unmaps, it is guaranteed that no stale
- * mappings will remain in the device or host TLBs.
- */
-struct gnttab_unmap_and_replace {
- /* IN parameters. */
- uint64_t host_addr;
- uint64_t new_addr;
- grant_handle_t handle;
- /* OUT parameters. */
- int16_t status; /* => enum grant_status */
-};
-typedef struct gnttab_unmap_and_replace gnttab_unmap_and_replace_t;
-DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_and_replace_t);
-
-#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
-/*
- * GNTTABOP_set_version: Request a particular version of the grant
- * table shared table structure. This operation can only be performed
- * once in any given domain. It must be performed before any grants
- * are activated; otherwise, the domain will be stuck with version 1.
- * The only defined versions are 1 and 2.
- */
-struct gnttab_set_version {
- /* IN/OUT parameters */
- uint32_t version;
-};
-typedef struct gnttab_set_version gnttab_set_version_t;
-DEFINE_XEN_GUEST_HANDLE(gnttab_set_version_t);
-
-
-/*
- * GNTTABOP_get_status_frames: Get the list of frames used to store grant
- * status for <dom>. In grant format version 2, the status is separated
- * from the other shared grant fields to allow more efficient synchronization
- * using barriers instead of atomic cmpexch operations.
- * <nr_frames> specify the size of vector <frame_list>.
- * The frame addresses are returned in the <frame_list>.
- * Only <nr_frames> addresses are returned, even if the table is larger.
- * NOTES:
- * 1. <dom> may be specified as DOMID_SELF.
- * 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
- */
-struct gnttab_get_status_frames {
- /* IN parameters. */
- uint32_t nr_frames;
- domid_t dom;
- /* OUT parameters. */
- int16_t status; /* => enum grant_status */
- XEN_GUEST_HANDLE(uint64_t) frame_list;
-};
-typedef struct gnttab_get_status_frames gnttab_get_status_frames_t;
-DEFINE_XEN_GUEST_HANDLE(gnttab_get_status_frames_t);
-
-/*
- * GNTTABOP_get_version: Get the grant table version which is in
- * effect for domain <dom>.
- */
-struct gnttab_get_version {
- /* IN parameters */
- domid_t dom;
- uint16_t pad;
- /* OUT parameters */
- uint32_t version;
-};
-typedef struct gnttab_get_version gnttab_get_version_t;
-DEFINE_XEN_GUEST_HANDLE(gnttab_get_version_t);
-
-/*
- * GNTTABOP_swap_grant_ref: Swap the contents of two grant entries.
- */
-struct gnttab_swap_grant_ref {
- /* IN parameters */
- grant_ref_t ref_a;
- grant_ref_t ref_b;
- /* OUT parameters */
- int16_t status; /* => enum grant_status */
-};
-typedef struct gnttab_swap_grant_ref gnttab_swap_grant_ref_t;
-DEFINE_XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t);
-
-/*
- * Issue one or more cache maintenance operations on a portion of a
- * page granted to the calling domain by a foreign domain.
- */
-struct gnttab_cache_flush {
- union {
- uint64_t dev_bus_addr;
- grant_ref_t ref;
- } a;
- uint16_t offset; /* offset from start of grant */
- uint16_t length; /* size within the grant */
-#define GNTTAB_CACHE_CLEAN (1<<0)
-#define GNTTAB_CACHE_INVAL (1<<1)
-#define GNTTAB_CACHE_SOURCE_GREF (1<<31)
- uint32_t op;
-};
-typedef struct gnttab_cache_flush gnttab_cache_flush_t;
-DEFINE_XEN_GUEST_HANDLE(gnttab_cache_flush_t);
-
-#endif /* __XEN_INTERFACE_VERSION__ */
-
-/*
- * Bitfield values for gnttab_map_grant_ref.flags.
- */
- /* Map the grant entry for access by I/O devices. */
-#define _GNTMAP_device_map (0)
-#define GNTMAP_device_map (1<<_GNTMAP_device_map)
- /* Map the grant entry for access by host CPUs. */
-#define _GNTMAP_host_map (1)
-#define GNTMAP_host_map (1<<_GNTMAP_host_map)
- /* Accesses to the granted frame will be restricted to read-only access. */
-#define _GNTMAP_readonly (2)
-#define GNTMAP_readonly (1<<_GNTMAP_readonly)
- /*
- * GNTMAP_host_map subflag:
- * 0 => The host mapping is usable only by the guest OS.
- * 1 => The host mapping is usable by guest OS + current application.
- */
-#define _GNTMAP_application_map (3)
-#define GNTMAP_application_map (1<<_GNTMAP_application_map)
-
- /*
- * GNTMAP_contains_pte subflag:
- * 0 => This map request contains a host virtual address.
- * 1 => This map request contains the machine addess of the PTE to update.
- */
-#define _GNTMAP_contains_pte (4)
-#define GNTMAP_contains_pte (1<<_GNTMAP_contains_pte)
-
-#define _GNTMAP_can_fail (5)
-#define GNTMAP_can_fail (1<<_GNTMAP_can_fail)
-
-/*
- * Bits to be placed in guest kernel available PTE bits (architecture
- * dependent; only supported when XENFEAT_gnttab_map_avail_bits is set).
- */
-#define _GNTMAP_guest_avail0 (16)
-#define GNTMAP_guest_avail_mask ((uint32_t)~0 << _GNTMAP_guest_avail0)
-
-/*
- * Values for error status returns. All errors are -ve.
- */
-/* ` enum grant_status { */
-#define GNTST_okay (0) /* Normal return. */
-#define GNTST_general_error (-1) /* General undefined error. */
-#define GNTST_bad_domain (-2) /* Unrecognsed domain id. */
-#define GNTST_bad_gntref (-3) /* Unrecognised or inappropriate gntref. */
-#define GNTST_bad_handle (-4) /* Unrecognised or inappropriate handle. */
-#define GNTST_bad_virt_addr (-5) /* Inappropriate virtual address to map. */
-#define GNTST_bad_dev_addr (-6) /* Inappropriate device address to unmap.*/
-#define GNTST_no_device_space (-7) /* Out of space in I/O MMU. */
-#define GNTST_permission_denied (-8) /* Not enough privilege for operation. */
-#define GNTST_bad_page (-9) /* Specified page was invalid for op. */
-#define GNTST_bad_copy_arg (-10) /* copy arguments cross page boundary. */
-#define GNTST_address_too_big (-11) /* transfer page address too large. */
-#define GNTST_eagain (-12) /* Operation not done; try again. */
-/* ` } */
-
-#define GNTTABOP_error_msgs { \
- "okay", \
- "undefined error", \
- "unrecognised domain id", \
- "invalid grant reference", \
- "invalid mapping handle", \
- "invalid virtual address", \
- "invalid device address", \
- "no spare translation slot in the I/O MMU", \
- "permission denied", \
- "bad page", \
- "copy arguments cross page boundary", \
- "page address size too large", \
- "operation not done; try again" \
-}
-
-#endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __XEN_PUBLIC_HVM_E820_H__
-#define __XEN_PUBLIC_HVM_E820_H__
-
-/* E820 location in HVM virtual address space. */
-#define HVM_E820_PAGE 0x00090000
-#define HVM_E820_NR_OFFSET 0x000001E8
-#define HVM_E820_OFFSET 0x000002D0
-
-#define HVM_BELOW_4G_RAM_END 0xF0000000
-#define HVM_BELOW_4G_MMIO_START HVM_BELOW_4G_RAM_END
-#define HVM_BELOW_4G_MMIO_LENGTH ((1ULL << 32) - HVM_BELOW_4G_MMIO_START)
-
-#endif /* __XEN_PUBLIC_HVM_E820_H__ */
+++ /dev/null
-/******************************************************************************
- * hvm/hvm_info_table.h
- *
- * HVM parameter and information table, written into guest memory map.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__
-#define __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__
-
-#define HVM_INFO_PFN 0x09F
-#define HVM_INFO_OFFSET 0x800
-#define HVM_INFO_PADDR ((HVM_INFO_PFN << 12) + HVM_INFO_OFFSET)
-
-/* Maximum we can support with current vLAPIC ID mapping. */
-#define HVM_MAX_VCPUS 128
-
-struct hvm_info_table {
- char signature[8]; /* "HVM INFO" */
- uint32_t length;
- uint8_t checksum;
-
- /* Should firmware build APIC descriptors (APIC MADT / MP BIOS)? */
- uint8_t apic_mode;
-
- /* How many CPUs does this domain have? */
- uint32_t nr_vcpus;
-
- /*
- * MEMORY MAP provided by HVM domain builder.
- * Notes:
- * 1. page_to_phys(x) = x << 12
- * 2. If a field is zero, the corresponding range does not exist.
- */
- /*
- * 0x0 to page_to_phys(low_mem_pgend)-1:
- * RAM below 4GB (except for VGA hole 0xA0000-0xBFFFF)
- */
- uint32_t low_mem_pgend;
- /*
- * page_to_phys(reserved_mem_pgstart) to 0xFFFFFFFF:
- * Reserved for special memory mappings
- */
- uint32_t reserved_mem_pgstart;
- /*
- * 0x100000000 to page_to_phys(high_mem_pgend)-1:
- * RAM above 4GB
- */
- uint32_t high_mem_pgend;
-
- /* Bitmap of which CPUs are online at boot time. */
- uint8_t vcpu_online[(HVM_MAX_VCPUS + 7)/8];
-};
-
-#endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */
+++ /dev/null
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __XEN_PUBLIC_HVM_HVM_OP_H__
-#define __XEN_PUBLIC_HVM_HVM_OP_H__
-
-#include "../xen.h"
-#include "../trace.h"
-#include "../event_channel.h"
-
-/* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
-#define HVMOP_set_param 0
-#define HVMOP_get_param 1
-struct xen_hvm_param {
- domid_t domid; /* IN */
- uint32_t index; /* IN */
- uint64_t value; /* IN/OUT */
-};
-typedef struct xen_hvm_param xen_hvm_param_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_param_t);
-
-/* Set the logical level of one of a domain's PCI INTx wires. */
-#define HVMOP_set_pci_intx_level 2
-struct xen_hvm_set_pci_intx_level {
- /* Domain to be updated. */
- domid_t domid;
- /* PCI INTx identification in PCI topology (domain:bus:device:intx). */
- uint8_t domain, bus, device, intx;
- /* Assertion level (0 = unasserted, 1 = asserted). */
- uint8_t level;
-};
-typedef struct xen_hvm_set_pci_intx_level xen_hvm_set_pci_intx_level_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_intx_level_t);
-
-/* Set the logical level of one of a domain's ISA IRQ wires. */
-#define HVMOP_set_isa_irq_level 3
-struct xen_hvm_set_isa_irq_level {
- /* Domain to be updated. */
- domid_t domid;
- /* ISA device identification, by ISA IRQ (0-15). */
- uint8_t isa_irq;
- /* Assertion level (0 = unasserted, 1 = asserted). */
- uint8_t level;
-};
-typedef struct xen_hvm_set_isa_irq_level xen_hvm_set_isa_irq_level_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_isa_irq_level_t);
-
-#define HVMOP_set_pci_link_route 4
-struct xen_hvm_set_pci_link_route {
- /* Domain to be updated. */
- domid_t domid;
- /* PCI link identifier (0-3). */
- uint8_t link;
- /* ISA IRQ (1-15), or 0 (disable link). */
- uint8_t isa_irq;
-};
-typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t);
-
-/* Flushes all VCPU TLBs: @arg must be NULL. */
-#define HVMOP_flush_tlbs 5
-
-typedef enum {
- HVMMEM_ram_rw, /* Normal read/write guest RAM */
- HVMMEM_ram_ro, /* Read-only; writes are discarded */
- HVMMEM_mmio_dm, /* Reads and write go to the device model */
- HVMMEM_mmio_write_dm /* Read-only; writes go to the device model */
-} hvmmem_type_t;
-
-/* Following tools-only interfaces may change in future. */
-#if defined(__XEN__) || defined(__XEN_TOOLS__)
-
-/* Track dirty VRAM. */
-#define HVMOP_track_dirty_vram 6
-struct xen_hvm_track_dirty_vram {
- /* Domain to be tracked. */
- domid_t domid;
- /* Number of pages to track. */
- uint32_t nr;
- /* First pfn to track. */
- uint64_aligned_t first_pfn;
- /* OUT variable. */
- /* Dirty bitmap buffer. */
- XEN_GUEST_HANDLE_64(uint8) dirty_bitmap;
-};
-typedef struct xen_hvm_track_dirty_vram xen_hvm_track_dirty_vram_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_track_dirty_vram_t);
-
-/* Notify that some pages got modified by the Device Model. */
-#define HVMOP_modified_memory 7
-struct xen_hvm_modified_memory {
- /* Domain to be updated. */
- domid_t domid;
- /* Number of pages. */
- uint32_t nr;
- /* First pfn. */
- uint64_aligned_t first_pfn;
-};
-typedef struct xen_hvm_modified_memory xen_hvm_modified_memory_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_modified_memory_t);
-
-#define HVMOP_set_mem_type 8
-/* Notify that a region of memory is to be treated in a specific way. */
-struct xen_hvm_set_mem_type {
- /* Domain to be updated. */
- domid_t domid;
- /* Memory type */
- uint16_t hvmmem_type;
- /* Number of pages. */
- uint32_t nr;
- /* First pfn. */
- uint64_aligned_t first_pfn;
-};
-typedef struct xen_hvm_set_mem_type xen_hvm_set_mem_type_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_mem_type_t);
-
-#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
-
-/* Hint from PV drivers for pagetable destruction. */
-#define HVMOP_pagetable_dying 9
-struct xen_hvm_pagetable_dying {
- /* Domain with a pagetable about to be destroyed. */
- domid_t domid;
- uint16_t pad[3]; /* align next field on 8-byte boundary */
- /* guest physical address of the toplevel pagetable dying */
- uint64_t gpa;
-};
-typedef struct xen_hvm_pagetable_dying xen_hvm_pagetable_dying_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_pagetable_dying_t);
-
-/* Get the current Xen time, in nanoseconds since system boot. */
-#define HVMOP_get_time 10
-struct xen_hvm_get_time {
- uint64_t now; /* OUT */
-};
-typedef struct xen_hvm_get_time xen_hvm_get_time_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_time_t);
-
-#define HVMOP_xentrace 11
-struct xen_hvm_xentrace {
- uint16_t event, extra_bytes;
- uint8_t extra[TRACE_EXTRA_MAX * sizeof(uint32_t)];
-};
-typedef struct xen_hvm_xentrace xen_hvm_xentrace_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_xentrace_t);
-
-/* Following tools-only interfaces may change in future. */
-#if defined(__XEN__) || defined(__XEN_TOOLS__)
-
-/* Deprecated by XENMEM_access_op_set_access */
-#define HVMOP_set_mem_access 12
-
-/* Deprecated by XENMEM_access_op_get_access */
-#define HVMOP_get_mem_access 13
-
-#define HVMOP_inject_trap 14
-/* Inject a trap into a VCPU, which will get taken up on the next
- * scheduling of it. Note that the caller should know enough of the
- * state of the CPU before injecting, to know what the effect of
- * injecting the trap will be.
- */
-struct xen_hvm_inject_trap {
- /* Domain to be queried. */
- domid_t domid;
- /* VCPU */
- uint32_t vcpuid;
- /* Vector number */
- uint32_t vector;
- /* Trap type (HVMOP_TRAP_*) */
- uint32_t type;
-/* NB. This enumeration precisely matches hvm.h:X86_EVENTTYPE_* */
-# define HVMOP_TRAP_ext_int 0 /* external interrupt */
-# define HVMOP_TRAP_nmi 2 /* nmi */
-# define HVMOP_TRAP_hw_exc 3 /* hardware exception */
-# define HVMOP_TRAP_sw_int 4 /* software interrupt (CD nn) */
-# define HVMOP_TRAP_pri_sw_exc 5 /* ICEBP (F1) */
-# define HVMOP_TRAP_sw_exc 6 /* INT3 (CC), INTO (CE) */
- /* Error code, or ~0u to skip */
- uint32_t error_code;
- /* Intruction length */
- uint32_t insn_len;
- /* CR2 for page faults */
- uint64_aligned_t cr2;
-};
-typedef struct xen_hvm_inject_trap xen_hvm_inject_trap_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_inject_trap_t);
-
-#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
-
-#define HVMOP_get_mem_type 15
-/* Return hvmmem_type_t for the specified pfn. */
-struct xen_hvm_get_mem_type {
- /* Domain to be queried. */
- domid_t domid;
- /* OUT variable. */
- uint16_t mem_type;
- uint16_t pad[2]; /* align next field on 8-byte boundary */
- /* IN variable. */
- uint64_t pfn;
-};
-typedef struct xen_hvm_get_mem_type xen_hvm_get_mem_type_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_mem_type_t);
-
-/* Following tools-only interfaces may change in future. */
-#if defined(__XEN__) || defined(__XEN_TOOLS__)
-
-/* MSI injection for emulated devices */
-#define HVMOP_inject_msi 16
-struct xen_hvm_inject_msi {
- /* Domain to be injected */
- domid_t domid;
- /* Data -- lower 32 bits */
- uint32_t data;
- /* Address (0xfeexxxxx) */
- uint64_t addr;
-};
-typedef struct xen_hvm_inject_msi xen_hvm_inject_msi_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_inject_msi_t);
-
-/*
- * IOREQ Servers
- *
- * The interface between an I/O emulator an Xen is called an IOREQ Server.
- * A domain supports a single 'legacy' IOREQ Server which is instantiated if
- * parameter...
- *
- * HVM_PARAM_IOREQ_PFN is read (to get the gmfn containing the synchronous
- * ioreq structures), or...
- * HVM_PARAM_BUFIOREQ_PFN is read (to get the gmfn containing the buffered
- * ioreq ring), or...
- * HVM_PARAM_BUFIOREQ_EVTCHN is read (to get the event channel that Xen uses
- * to request buffered I/O emulation).
- *
- * The following hypercalls facilitate the creation of IOREQ Servers for
- * 'secondary' emulators which are invoked to implement port I/O, memory, or
- * PCI config space ranges which they explicitly register.
- */
-
-typedef uint16_t ioservid_t;
-
-/*
- * HVMOP_create_ioreq_server: Instantiate a new IOREQ Server for a secondary
- * emulator servicing domain <domid>.
- *
- * The <id> handed back is unique for <domid>. If <handle_bufioreq> is zero
- * the buffered ioreq ring will not be allocated and hence all emulation
- * requestes to this server will be synchronous.
- */
-#define HVMOP_create_ioreq_server 17
-struct xen_hvm_create_ioreq_server {
- domid_t domid; /* IN - domain to be serviced */
- uint8_t handle_bufioreq; /* IN - should server handle buffered ioreqs */
- ioservid_t id; /* OUT - server id */
-};
-typedef struct xen_hvm_create_ioreq_server xen_hvm_create_ioreq_server_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_create_ioreq_server_t);
-
-/*
- * HVMOP_get_ioreq_server_info: Get all the information necessary to access
- * IOREQ Server <id>.
- *
- * The emulator needs to map the synchronous ioreq structures and buffered
- * ioreq ring (if it exists) that Xen uses to request emulation. These are
- * hosted in domain <domid>'s gmfns <ioreq_pfn> and <bufioreq_pfn>
- * respectively. In addition, if the IOREQ Server is handling buffered
- * emulation requests, the emulator needs to bind to event channel
- * <bufioreq_port> to listen for them. (The event channels used for
- * synchronous emulation requests are specified in the per-CPU ioreq
- * structures in <ioreq_pfn>).
- * If the IOREQ Server is not handling buffered emulation requests then the
- * values handed back in <bufioreq_pfn> and <bufioreq_port> will both be 0.
- */
-#define HVMOP_get_ioreq_server_info 18
-struct xen_hvm_get_ioreq_server_info {
- domid_t domid; /* IN - domain to be serviced */
- ioservid_t id; /* IN - server id */
- evtchn_port_t bufioreq_port; /* OUT - buffered ioreq port */
- uint64_aligned_t ioreq_pfn; /* OUT - sync ioreq pfn */
- uint64_aligned_t bufioreq_pfn; /* OUT - buffered ioreq pfn */
-};
-typedef struct xen_hvm_get_ioreq_server_info xen_hvm_get_ioreq_server_info_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_ioreq_server_info_t);
-
-/*
- * HVM_map_io_range_to_ioreq_server: Register an I/O range of domain <domid>
- * for emulation by the client of IOREQ
- * Server <id>
- * HVM_unmap_io_range_from_ioreq_server: Deregister an I/O range of <domid>
- * for emulation by the client of IOREQ
- * Server <id>
- *
- * There are three types of I/O that can be emulated: port I/O, memory accesses
- * and PCI config space accesses. The <type> field denotes which type of range
- * the <start> and <end> (inclusive) fields are specifying.
- * PCI config space ranges are specified by segment/bus/device/function values
- * which should be encoded using the HVMOP_PCI_SBDF helper macro below.
- *
- * NOTE: unless an emulation request falls entirely within a range mapped
- * by a secondary emulator, it will not be passed to that emulator.
- */
-#define HVMOP_map_io_range_to_ioreq_server 19
-#define HVMOP_unmap_io_range_from_ioreq_server 20
-struct xen_hvm_io_range {
- domid_t domid; /* IN - domain to be serviced */
- ioservid_t id; /* IN - server id */
- uint32_t type; /* IN - type of range */
-# define HVMOP_IO_RANGE_PORT 0 /* I/O port range */
-# define HVMOP_IO_RANGE_MEMORY 1 /* MMIO range */
-# define HVMOP_IO_RANGE_PCI 2 /* PCI segment/bus/dev/func range */
- uint64_aligned_t start, end; /* IN - inclusive start and end of range */
-};
-typedef struct xen_hvm_io_range xen_hvm_io_range_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_io_range_t);
-
-#define HVMOP_PCI_SBDF(s,b,d,f) \
- ((((s) & 0xffff) << 16) | \
- (((b) & 0xff) << 8) | \
- (((d) & 0x1f) << 3) | \
- ((f) & 0x07))
-
-/*
- * HVMOP_destroy_ioreq_server: Destroy the IOREQ Server <id> servicing domain
- * <domid>.
- *
- * Any registered I/O ranges will be automatically deregistered.
- */
-#define HVMOP_destroy_ioreq_server 21
-struct xen_hvm_destroy_ioreq_server {
- domid_t domid; /* IN - domain to be serviced */
- ioservid_t id; /* IN - server id */
-};
-typedef struct xen_hvm_destroy_ioreq_server xen_hvm_destroy_ioreq_server_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_destroy_ioreq_server_t);
-
-/*
- * HVMOP_set_ioreq_server_state: Enable or disable the IOREQ Server <id> servicing
- * domain <domid>.
- *
- * The IOREQ Server will not be passed any emulation requests until it is in the
- * enabled state.
- * Note that the contents of the ioreq_pfn and bufioreq_fn (see
- * HVMOP_get_ioreq_server_info) are not meaningful until the IOREQ Server is in
- * the enabled state.
- */
-#define HVMOP_set_ioreq_server_state 22
-struct xen_hvm_set_ioreq_server_state {
- domid_t domid; /* IN - domain to be serviced */
- ioservid_t id; /* IN - server id */
- uint8_t enabled; /* IN - enabled? */
-};
-typedef struct xen_hvm_set_ioreq_server_state xen_hvm_set_ioreq_server_state_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_ioreq_server_state_t);
-
-#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
-
-#if defined(__i386__) || defined(__x86_64__)
-
-/*
- * HVMOP_set_evtchn_upcall_vector: Set a <vector> that should be used for event
- * channel upcalls on the specified <vcpu>. If set,
- * this vector will be used in preference to the
- * domain global callback via (see
- * HVM_PARAM_CALLBACK_IRQ).
- */
-#define HVMOP_set_evtchn_upcall_vector 23
-struct xen_hvm_evtchn_upcall_vector {
- uint32_t vcpu;
- uint8_t vector;
-};
-typedef struct xen_hvm_evtchn_upcall_vector xen_hvm_evtchn_upcall_vector_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_evtchn_upcall_vector_t);
-
-#endif /* defined(__i386__) || defined(__x86_64__) */
-
-#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * hvm/hvm_xs_strings.h
- *
- * HVM xenstore strings used in HVMLOADER.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __XEN_PUBLIC_HVM_HVM_XS_STRINGS_H__
-#define __XEN_PUBLIC_HVM_HVM_XS_STRINGS_H__
-
-#define HVM_XS_HVMLOADER "hvmloader"
-#define HVM_XS_BIOS "hvmloader/bios"
-#define HVM_XS_GENERATION_ID_ADDRESS "hvmloader/generation-id-address"
-#define HVM_XS_ALLOW_MEMORY_RELOCATE "hvmloader/allow-memory-relocate"
-
-/* The following values allow additional ACPI tables to be added to the
- * virtual ACPI BIOS that hvmloader constructs. The values specify the guest
- * physical address and length of a block of ACPI tables to add. The format of
- * the block is simply concatenated raw tables (which specify their own length
- * in the ACPI header).
- */
-#define HVM_XS_ACPI_PT_ADDRESS "hvmloader/acpi/address"
-#define HVM_XS_ACPI_PT_LENGTH "hvmloader/acpi/length"
-
-/* Any number of SMBIOS types can be passed through to an HVM guest using
- * the following xenstore values. The values specify the guest physical
- * address and length of a block of SMBIOS structures for hvmloader to use.
- * The block is formatted in the following way:
- *
- * <length><struct><length><struct>...
- *
- * Each length separator is a 32b integer indicating the length of the next
- * SMBIOS structure. For DMTF defined types (0 - 121), the passed in struct
- * will replace the default structure in hvmloader. In addition, any
- * OEM/vendortypes (128 - 255) will all be added.
- */
-#define HVM_XS_SMBIOS_PT_ADDRESS "hvmloader/smbios/address"
-#define HVM_XS_SMBIOS_PT_LENGTH "hvmloader/smbios/length"
-
-/* Set to 1 to enable SMBIOS default portable battery (type 22) values. */
-#define HVM_XS_SMBIOS_DEFAULT_BATTERY "hvmloader/smbios/default_battery"
-
-/* The following xenstore values are used to override some of the default
- * string values in the SMBIOS table constructed in hvmloader.
- */
-#define HVM_XS_BIOS_STRINGS "bios-strings"
-#define HVM_XS_BIOS_VENDOR "bios-strings/bios-vendor"
-#define HVM_XS_BIOS_VERSION "bios-strings/bios-version"
-#define HVM_XS_SYSTEM_MANUFACTURER "bios-strings/system-manufacturer"
-#define HVM_XS_SYSTEM_PRODUCT_NAME "bios-strings/system-product-name"
-#define HVM_XS_SYSTEM_VERSION "bios-strings/system-version"
-#define HVM_XS_SYSTEM_SERIAL_NUMBER "bios-strings/system-serial-number"
-#define HVM_XS_ENCLOSURE_MANUFACTURER "bios-strings/enclosure-manufacturer"
-#define HVM_XS_ENCLOSURE_SERIAL_NUMBER "bios-strings/enclosure-serial-number"
-#define HVM_XS_BATTERY_MANUFACTURER "bios-strings/battery-manufacturer"
-#define HVM_XS_BATTERY_DEVICE_NAME "bios-strings/battery-device-name"
-
-/* 1 to 99 OEM strings can be set in xenstore using values of the form
- * below. These strings will be loaded into the SMBIOS type 11 structure.
- */
-#define HVM_XS_OEM_STRINGS "bios-strings/oem-%d"
-
-#endif /* __XEN_PUBLIC_HVM_HVM_XS_STRINGS_H__ */
+++ /dev/null
-/*
- * ioreq.h: I/O request definitions for device models
- * Copyright (c) 2004, Intel Corporation.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _IOREQ_H_
-#define _IOREQ_H_
-
-#define IOREQ_READ 1
-#define IOREQ_WRITE 0
-
-#define STATE_IOREQ_NONE 0
-#define STATE_IOREQ_READY 1
-#define STATE_IOREQ_INPROCESS 2
-#define STATE_IORESP_READY 3
-
-#define IOREQ_TYPE_PIO 0 /* pio */
-#define IOREQ_TYPE_COPY 1 /* mmio ops */
-#define IOREQ_TYPE_PCI_CONFIG 2
-#define IOREQ_TYPE_TIMEOFFSET 7
-#define IOREQ_TYPE_INVALIDATE 8 /* mapcache */
-
-/*
- * VMExit dispatcher should cooperate with instruction decoder to
- * prepare this structure and notify service OS and DM by sending
- * virq.
- *
- * For I/O type IOREQ_TYPE_PCI_CONFIG, the physical address is formatted
- * as follows:
- *
- * 63....48|47..40|39..35|34..32|31........0
- * SEGMENT |BUS |DEV |FN |OFFSET
- */
-struct ioreq {
- uint64_t addr; /* physical address */
- uint64_t data; /* data (or paddr of data) */
- uint32_t count; /* for rep prefixes */
- uint32_t size; /* size in bytes */
- uint32_t vp_eport; /* evtchn for notifications to/from device model */
- uint16_t _pad0;
- uint8_t state:4;
- uint8_t data_is_ptr:1; /* if 1, data above is the guest paddr
- * of the real data to use. */
- uint8_t dir:1; /* 1=read, 0=write */
- uint8_t df:1;
- uint8_t _pad1:1;
- uint8_t type; /* I/O type */
-};
-typedef struct ioreq ioreq_t;
-
-struct shared_iopage {
- struct ioreq vcpu_ioreq[1];
-};
-typedef struct shared_iopage shared_iopage_t;
-
-struct buf_ioreq {
- uint8_t type; /* I/O type */
- uint8_t pad:1;
- uint8_t dir:1; /* 1=read, 0=write */
- uint8_t size:2; /* 0=>1, 1=>2, 2=>4, 3=>8. If 8, use two buf_ioreqs */
- uint32_t addr:20;/* physical address */
- uint32_t data; /* data */
-};
-typedef struct buf_ioreq buf_ioreq_t;
-
-#define IOREQ_BUFFER_SLOT_NUM 511 /* 8 bytes each, plus 2 4-byte indexes */
-struct buffered_iopage {
- unsigned int read_pointer;
- unsigned int write_pointer;
- buf_ioreq_t buf_ioreq[IOREQ_BUFFER_SLOT_NUM];
-}; /* NB. Size of this structure must be no greater than one page. */
-typedef struct buffered_iopage buffered_iopage_t;
-
-/*
- * ACPI Control/Event register locations. Location is controlled by a
- * version number in HVM_PARAM_ACPI_IOPORTS_LOCATION.
- */
-
-/* Version 0 (default): Traditional Xen locations. */
-#define ACPI_PM1A_EVT_BLK_ADDRESS_V0 0x1f40
-#define ACPI_PM1A_CNT_BLK_ADDRESS_V0 (ACPI_PM1A_EVT_BLK_ADDRESS_V0 + 0x04)
-#define ACPI_PM_TMR_BLK_ADDRESS_V0 (ACPI_PM1A_EVT_BLK_ADDRESS_V0 + 0x08)
-#define ACPI_GPE0_BLK_ADDRESS_V0 (ACPI_PM_TMR_BLK_ADDRESS_V0 + 0x20)
-#define ACPI_GPE0_BLK_LEN_V0 0x08
-
-/* Version 1: Locations preferred by modern Qemu. */
-#define ACPI_PM1A_EVT_BLK_ADDRESS_V1 0xb000
-#define ACPI_PM1A_CNT_BLK_ADDRESS_V1 (ACPI_PM1A_EVT_BLK_ADDRESS_V1 + 0x04)
-#define ACPI_PM_TMR_BLK_ADDRESS_V1 (ACPI_PM1A_EVT_BLK_ADDRESS_V1 + 0x08)
-#define ACPI_GPE0_BLK_ADDRESS_V1 0xafe0
-#define ACPI_GPE0_BLK_LEN_V1 0x04
-
-/* Compatibility definitions for the default location (version 0). */
-#define ACPI_PM1A_EVT_BLK_ADDRESS ACPI_PM1A_EVT_BLK_ADDRESS_V0
-#define ACPI_PM1A_CNT_BLK_ADDRESS ACPI_PM1A_CNT_BLK_ADDRESS_V0
-#define ACPI_PM_TMR_BLK_ADDRESS ACPI_PM_TMR_BLK_ADDRESS_V0
-#define ACPI_GPE0_BLK_ADDRESS ACPI_GPE0_BLK_ADDRESS_V0
-#define ACPI_GPE0_BLK_LEN ACPI_GPE0_BLK_LEN_V0
-
-
-#endif /* _IOREQ_H_ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __XEN_PUBLIC_HVM_PARAMS_H__
-#define __XEN_PUBLIC_HVM_PARAMS_H__
-
-#include "hvm_op.h"
-
-/*
- * Parameter space for HVMOP_{set,get}_param.
- */
-
-/*
- * How should CPU0 event-channel notifications be delivered?
- * val[63:56] == 0: val[55:0] is a delivery GSI (Global System Interrupt).
- * val[63:56] == 1: val[55:0] is a delivery PCI INTx line, as follows:
- * Domain = val[47:32], Bus = val[31:16],
- * DevFn = val[15: 8], IntX = val[ 1: 0]
- * val[63:56] == 2: val[7:0] is a vector number, check for
- * XENFEAT_hvm_callback_vector to know if this delivery
- * method is available.
- * If val == 0 then CPU0 event-channel notifications are not delivered.
- */
-#define HVM_PARAM_CALLBACK_IRQ 0
-
-/*
- * These are not used by Xen. They are here for convenience of HVM-guest
- * xenbus implementations.
- */
-#define HVM_PARAM_STORE_PFN 1
-#define HVM_PARAM_STORE_EVTCHN 2
-
-#define HVM_PARAM_PAE_ENABLED 4
-
-#define HVM_PARAM_IOREQ_PFN 5
-
-#define HVM_PARAM_BUFIOREQ_PFN 6
-#define HVM_PARAM_BUFIOREQ_EVTCHN 26
-
-#if defined(__i386__) || defined(__x86_64__)
-
-/*
- * Viridian enlightenments
- *
- * (See http://download.microsoft.com/download/A/B/4/AB43A34E-BDD0-4FA6-BDEF-79EEF16E880B/Hypervisor%20Top%20Level%20Functional%20Specification%20v4.0.docx)
- *
- * To expose viridian enlightenments to the guest set this parameter
- * to the desired feature mask. The base feature set must be present
- * in any valid feature mask.
- */
-#define HVM_PARAM_VIRIDIAN 9
-
-/* Base+Freq viridian feature sets:
- *
- * - Hypercall MSRs (HV_X64_MSR_GUEST_OS_ID and HV_X64_MSR_HYPERCALL)
- * - APIC access MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR)
- * - Virtual Processor index MSR (HV_X64_MSR_VP_INDEX)
- * - Timer frequency MSRs (HV_X64_MSR_TSC_FREQUENCY and
- * HV_X64_MSR_APIC_FREQUENCY)
- */
-#define _HVMPV_base_freq 0
-#define HVMPV_base_freq (1 << _HVMPV_base_freq)
-
-/* Feature set modifications */
-
-/* Disable timer frequency MSRs (HV_X64_MSR_TSC_FREQUENCY and
- * HV_X64_MSR_APIC_FREQUENCY).
- * This modification restores the viridian feature set to the
- * original 'base' set exposed in releases prior to Xen 4.4.
- */
-#define _HVMPV_no_freq 1
-#define HVMPV_no_freq (1 << _HVMPV_no_freq)
-
-/* Enable Partition Time Reference Counter (HV_X64_MSR_TIME_REF_COUNT) */
-#define _HVMPV_time_ref_count 2
-#define HVMPV_time_ref_count (1 << _HVMPV_time_ref_count)
-
-/* Enable Reference TSC Page (HV_X64_MSR_REFERENCE_TSC) */
-#define _HVMPV_reference_tsc 3
-#define HVMPV_reference_tsc (1 << _HVMPV_reference_tsc)
-
-#define HVMPV_feature_mask \
- (HVMPV_base_freq | \
- HVMPV_no_freq | \
- HVMPV_time_ref_count | \
- HVMPV_reference_tsc)
-
-#endif
-
-/*
- * Set mode for virtual timers (currently x86 only):
- * delay_for_missed_ticks (default):
- * Do not advance a vcpu's time beyond the correct delivery time for
- * interrupts that have been missed due to preemption. Deliver missed
- * interrupts when the vcpu is rescheduled and advance the vcpu's virtual
- * time stepwise for each one.
- * no_delay_for_missed_ticks:
- * As above, missed interrupts are delivered, but guest time always tracks
- * wallclock (i.e., real) time while doing so.
- * no_missed_ticks_pending:
- * No missed interrupts are held pending. Instead, to ensure ticks are
- * delivered at some non-zero rate, if we detect missed ticks then the
- * internal tick alarm is not disabled if the VCPU is preempted during the
- * next tick period.
- * one_missed_tick_pending:
- * Missed interrupts are collapsed together and delivered as one 'late tick'.
- * Guest time always tracks wallclock (i.e., real) time.
- */
-#define HVM_PARAM_TIMER_MODE 10
-#define HVMPTM_delay_for_missed_ticks 0
-#define HVMPTM_no_delay_for_missed_ticks 1
-#define HVMPTM_no_missed_ticks_pending 2
-#define HVMPTM_one_missed_tick_pending 3
-
-/* Boolean: Enable virtual HPET (high-precision event timer)? (x86-only) */
-#define HVM_PARAM_HPET_ENABLED 11
-
-/* Identity-map page directory used by Intel EPT when CR0.PG=0. */
-#define HVM_PARAM_IDENT_PT 12
-
-/* Device Model domain, defaults to 0. */
-#define HVM_PARAM_DM_DOMAIN 13
-
-/* ACPI S state: currently support S0 and S3 on x86. */
-#define HVM_PARAM_ACPI_S_STATE 14
-
-/* TSS used on Intel when CR0.PE=0. */
-#define HVM_PARAM_VM86_TSS 15
-
-/* Boolean: Enable aligning all periodic vpts to reduce interrupts */
-#define HVM_PARAM_VPT_ALIGN 16
-
-/* Console debug shared memory ring and event channel */
-#define HVM_PARAM_CONSOLE_PFN 17
-#define HVM_PARAM_CONSOLE_EVTCHN 18
-
-/*
- * Select location of ACPI PM1a and TMR control blocks. Currently two locations
- * are supported, specified by version 0 or 1 in this parameter:
- * - 0: default, use the old addresses
- * PM1A_EVT == 0x1f40; PM1A_CNT == 0x1f44; PM_TMR == 0x1f48
- * - 1: use the new default qemu addresses
- * PM1A_EVT == 0xb000; PM1A_CNT == 0xb004; PM_TMR == 0xb008
- * You can find these address definitions in <hvm/ioreq.h>
- */
-#define HVM_PARAM_ACPI_IOPORTS_LOCATION 19
-
-/* Enable blocking memory events, async or sync (pause vcpu until response)
- * onchangeonly indicates messages only on a change of value */
-#define HVM_PARAM_MEMORY_EVENT_CR0 20
-#define HVM_PARAM_MEMORY_EVENT_CR3 21
-#define HVM_PARAM_MEMORY_EVENT_CR4 22
-#define HVM_PARAM_MEMORY_EVENT_INT3 23
-#define HVM_PARAM_MEMORY_EVENT_SINGLE_STEP 25
-#define HVM_PARAM_MEMORY_EVENT_MSR 30
-
-#define HVMPME_MODE_MASK (3 << 0)
-#define HVMPME_mode_disabled 0
-#define HVMPME_mode_async 1
-#define HVMPME_mode_sync 2
-#define HVMPME_onchangeonly (1 << 2)
-
-/* Boolean: Enable nestedhvm (hvm only) */
-#define HVM_PARAM_NESTEDHVM 24
-
-/* Params for the mem event rings */
-#define HVM_PARAM_PAGING_RING_PFN 27
-#define HVM_PARAM_ACCESS_RING_PFN 28
-#define HVM_PARAM_SHARING_RING_PFN 29
-
-/* SHUTDOWN_* action in case of a triple fault */
-#define HVM_PARAM_TRIPLE_FAULT_REASON 31
-
-#define HVM_PARAM_IOREQ_SERVER_PFN 32
-#define HVM_PARAM_NR_IOREQ_SERVER_PAGES 33
-
-/* Location of the VM Generation ID in guest physical address space. */
-#define HVM_PARAM_VM_GENERATION_ID_ADDR 34
-
-#define HVM_NR_PARAMS 35
-
-#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
+++ /dev/null
-/*
- * pvdrivers.h: Register of PV drivers product numbers.
- * Copyright (c) 2012, Citrix Systems Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _XEN_PUBLIC_PVDRIVERS_H_
-#define _XEN_PUBLIC_PVDRIVERS_H_
-
-/*
- * This is the master registry of product numbers for
- * PV drivers.
- * If you need a new product number allocating, please
- * post to xen-devel@lists.xensource.com. You should NOT use
- * a product number without allocating one.
- * If you maintain a separate versioning and distribution path
- * for PV drivers you should have a separate product number so
- * that your drivers can be separated from others.
- *
- * During development, you may use the product ID to
- * indicate a driver which is yet to be released.
- */
-
-#define PVDRIVERS_PRODUCT_LIST(EACH) \
- EACH("xensource-windows", 0x0001) /* Citrix */ \
- EACH("gplpv-windows", 0x0002) /* James Harper */ \
- EACH("linux", 0x0003) \
- EACH("xenserver-windows-v7.0+", 0x0004) /* Citrix */ \
- EACH("xenserver-windows-v7.2+", 0x0005) /* Citrix */ \
- EACH("experimental", 0xffff)
-
-#endif /* _XEN_PUBLIC_PVDRIVERS_H_ */
+++ /dev/null
-/*
- * hvm/save.h
- *
- * Structure definitions for HVM state that is held by Xen and must
- * be saved along with the domain's memory and device-model state.
- *
- * Copyright (c) 2007 XenSource Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __XEN_PUBLIC_HVM_SAVE_H__
-#define __XEN_PUBLIC_HVM_SAVE_H__
-
-/*
- * Structures in this header *must* have the same layout in 32bit
- * and 64bit environments: this means that all fields must be explicitly
- * sized types and aligned to their sizes, and the structs must be
- * a multiple of eight bytes long.
- *
- * Only the state necessary for saving and restoring (i.e. fields
- * that are analogous to actual hardware state) should go in this file.
- * Internal mechanisms should be kept in Xen-private headers.
- */
-
-#if !defined(__GNUC__) || defined(__STRICT_ANSI__)
-#error "Anonymous structs/unions are a GNU extension."
-#endif
-
-/*
- * Each entry is preceded by a descriptor giving its type and length
- */
-struct hvm_save_descriptor {
- uint16_t typecode; /* Used to demux the various types below */
- uint16_t instance; /* Further demux within a type */
- uint32_t length; /* In bytes, *not* including this descriptor */
-};
-
-
-/*
- * Each entry has a datatype associated with it: for example, the CPU state
- * is saved as a HVM_SAVE_TYPE(CPU), which has HVM_SAVE_LENGTH(CPU),
- * and is identified by a descriptor with typecode HVM_SAVE_CODE(CPU).
- * DECLARE_HVM_SAVE_TYPE binds these things together with some type-system
- * ugliness.
- */
-
-#ifdef __XEN__
-# define DECLARE_HVM_SAVE_TYPE_COMPAT(_x, _code, _type, _ctype, _fix) \
- static inline int __HVM_SAVE_FIX_COMPAT_##_x(void *h) { return _fix(h); } \
- struct __HVM_SAVE_TYPE_##_x { _type t; char c[_code]; char cpt[2];}; \
- struct __HVM_SAVE_TYPE_COMPAT_##_x { _ctype t; }
-
-# include <xen/lib.h> /* BUG() */
-# define DECLARE_HVM_SAVE_TYPE(_x, _code, _type) \
- static inline int __HVM_SAVE_FIX_COMPAT_##_x(void *h) { BUG(); return -1; } \
- struct __HVM_SAVE_TYPE_##_x { _type t; char c[_code]; char cpt[1];}; \
- struct __HVM_SAVE_TYPE_COMPAT_##_x { _type t; }
-#else
-# define DECLARE_HVM_SAVE_TYPE_COMPAT(_x, _code, _type, _ctype, _fix) \
- struct __HVM_SAVE_TYPE_##_x { _type t; char c[_code]; char cpt[2];}
-
-# define DECLARE_HVM_SAVE_TYPE(_x, _code, _type) \
- struct __HVM_SAVE_TYPE_##_x { _type t; char c[_code]; char cpt[1];}
-#endif
-
-#define HVM_SAVE_TYPE(_x) typeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->t)
-#define HVM_SAVE_LENGTH(_x) (sizeof (HVM_SAVE_TYPE(_x)))
-#define HVM_SAVE_CODE(_x) (sizeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->c))
-
-#ifdef __XEN__
-# define HVM_SAVE_TYPE_COMPAT(_x) typeof (((struct __HVM_SAVE_TYPE_COMPAT_##_x *)(0))->t)
-# define HVM_SAVE_LENGTH_COMPAT(_x) (sizeof (HVM_SAVE_TYPE_COMPAT(_x)))
-
-# define HVM_SAVE_HAS_COMPAT(_x) (sizeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->cpt)-1)
-# define HVM_SAVE_FIX_COMPAT(_x, _dst) __HVM_SAVE_FIX_COMPAT_##_x(_dst)
-#endif
-
-/*
- * The series of save records is teminated by a zero-type, zero-length
- * descriptor.
- */
-
-struct hvm_save_end {};
-DECLARE_HVM_SAVE_TYPE(END, 0, struct hvm_save_end);
-
-#if defined(__i386__) || defined(__x86_64__)
-#include "../arch-x86/hvm/save.h"
-#elif defined(__arm__) || defined(__aarch64__)
-#include "../arch-arm/hvm/save.h"
-#else
-#error "unsupported architecture"
-#endif
-
-#endif /* __XEN_PUBLIC_HVM_SAVE_H__ */
+++ /dev/null
-/******************************************************************************
- * blkif.h
- *
- * Unified block-device I/O interface for Xen guest OSes.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2003-2004, Keir Fraser
- * Copyright (c) 2012, Spectra Logic Corporation
- */
-
-#ifndef __XEN_PUBLIC_IO_BLKIF_H__
-#define __XEN_PUBLIC_IO_BLKIF_H__
-
-#include "ring.h"
-#include "../grant_table.h"
-
-/*
- * Front->back notifications: When enqueuing a new request, sending a
- * notification can be made conditional on req_event (i.e., the generic
- * hold-off mechanism provided by the ring macros). Backends must set
- * req_event appropriately (e.g., using RING_FINAL_CHECK_FOR_REQUESTS()).
- *
- * Back->front notifications: When enqueuing a new response, sending a
- * notification can be made conditional on rsp_event (i.e., the generic
- * hold-off mechanism provided by the ring macros). Frontends must set
- * rsp_event appropriately (e.g., using RING_FINAL_CHECK_FOR_RESPONSES()).
- */
-
-#ifndef blkif_vdev_t
-#define blkif_vdev_t uint16_t
-#endif
-#define blkif_sector_t uint64_t
-
-/*
- * Feature and Parameter Negotiation
- * =================================
- * The two halves of a Xen block driver utilize nodes within the XenStore to
- * communicate capabilities and to negotiate operating parameters. This
- * section enumerates these nodes which reside in the respective front and
- * backend portions of the XenStore, following the XenBus convention.
- *
- * All data in the XenStore is stored as strings. Nodes specifying numeric
- * values are encoded in decimal. Integer value ranges listed below are
- * expressed as fixed sized integer types capable of storing the conversion
- * of a properly formated node string, without loss of information.
- *
- * Any specified default value is in effect if the corresponding XenBus node
- * is not present in the XenStore.
- *
- * XenStore nodes in sections marked "PRIVATE" are solely for use by the
- * driver side whose XenBus tree contains them.
- *
- * XenStore nodes marked "DEPRECATED" in their notes section should only be
- * used to provide interoperability with legacy implementations.
- *
- * See the XenBus state transition diagram below for details on when XenBus
- * nodes must be published and when they can be queried.
- *
- *****************************************************************************
- * Backend XenBus Nodes
- *****************************************************************************
- *
- *------------------ Backend Device Identification (PRIVATE) ------------------
- *
- * mode
- * Values: "r" (read only), "w" (writable)
- *
- * The read or write access permissions to the backing store to be
- * granted to the frontend.
- *
- * params
- * Values: string
- *
- * A free formatted string providing sufficient information for the
- * backend driver to open the backing device. (e.g. the path to the
- * file or block device representing the backing store.)
- *
- * type
- * Values: "file", "phy", "tap"
- *
- * The type of the backing device/object.
- *
- *
- * direct-io-safe
- * Values: 0/1 (boolean)
- * Default Value: 0
- *
- * The underlying storage is not affected by the direct IO memory
- * lifetime bug. See:
- * http://lists.xen.org/archives/html/xen-devel/2012-12/msg01154.html
- *
- * Therefore this option gives the backend permission to use
- * O_DIRECT, notwithstanding that bug.
- *
- * That is, if this option is enabled, use of O_DIRECT is safe,
- * in circumstances where we would normally have avoided it as a
- * workaround for that bug. This option is not relevant for all
- * backends, and even not necessarily supported for those for
- * which it is relevant. A backend which knows that it is not
- * affected by the bug can ignore this option.
- *
- * This option doesn't require a backend to use O_DIRECT, so it
- * should not be used to try to control the caching behaviour.
- *
- *--------------------------------- Features ---------------------------------
- *
- * feature-barrier
- * Values: 0/1 (boolean)
- * Default Value: 0
- *
- * A value of "1" indicates that the backend can process requests
- * containing the BLKIF_OP_WRITE_BARRIER request opcode. Requests
- * of this type may still be returned at any time with the
- * BLKIF_RSP_EOPNOTSUPP result code.
- *
- * feature-flush-cache
- * Values: 0/1 (boolean)
- * Default Value: 0
- *
- * A value of "1" indicates that the backend can process requests
- * containing the BLKIF_OP_FLUSH_DISKCACHE request opcode. Requests
- * of this type may still be returned at any time with the
- * BLKIF_RSP_EOPNOTSUPP result code.
- *
- * feature-discard
- * Values: 0/1 (boolean)
- * Default Value: 0
- *
- * A value of "1" indicates that the backend can process requests
- * containing the BLKIF_OP_DISCARD request opcode. Requests
- * of this type may still be returned at any time with the
- * BLKIF_RSP_EOPNOTSUPP result code.
- *
- * feature-persistent
- * Values: 0/1 (boolean)
- * Default Value: 0
- * Notes: 7
- *
- * A value of "1" indicates that the backend can keep the grants used
- * by the frontend driver mapped, so the same set of grants should be
- * used in all transactions. The maximum number of grants the backend
- * can map persistently depends on the implementation, but ideally it
- * should be RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST. Using this
- * feature the backend doesn't need to unmap each grant, preventing
- * costly TLB flushes. The backend driver should only map grants
- * persistently if the frontend supports it. If a backend driver chooses
- * to use the persistent protocol when the frontend doesn't support it,
- * it will probably hit the maximum number of persistently mapped grants
- * (due to the fact that the frontend won't be reusing the same grants),
- * and fall back to non-persistent mode. Backend implementations may
- * shrink or expand the number of persistently mapped grants without
- * notifying the frontend depending on memory constraints (this might
- * cause a performance degradation).
- *
- * If a backend driver wants to limit the maximum number of persistently
- * mapped grants to a value less than RING_SIZE *
- * BLKIF_MAX_SEGMENTS_PER_REQUEST a LRU strategy should be used to
- * discard the grants that are less commonly used. Using a LRU in the
- * backend driver paired with a LIFO queue in the frontend will
- * allow us to have better performance in this scenario.
- *
- *----------------------- Request Transport Parameters ------------------------
- *
- * max-ring-page-order
- * Values: <uint32_t>
- * Default Value: 0
- * Notes: 1, 3
- *
- * The maximum supported size of the request ring buffer in units of
- * lb(machine pages). (e.g. 0 == 1 page, 1 = 2 pages, 2 == 4 pages,
- * etc.).
- *
- * max-ring-pages
- * Values: <uint32_t>
- * Default Value: 1
- * Notes: DEPRECATED, 2, 3
- *
- * The maximum supported size of the request ring buffer in units of
- * machine pages. The value must be a power of 2.
- *
- *------------------------- Backend Device Properties -------------------------
- *
- * discard-enable
- * Values: 0/1 (boolean)
- * Default Value: 1
- *
- * This optional property, set by the toolstack, instructs the backend
- * to offer discard to the frontend. If the property is missing the
- * backend should offer discard if the backing storage actually supports
- * it. This optional property, set by the toolstack, requests that the
- * backend offer, or not offer, discard to the frontend.
- *
- * discard-alignment
- * Values: <uint32_t>
- * Default Value: 0
- * Notes: 4, 5
- *
- * The offset, in bytes from the beginning of the virtual block device,
- * to the first, addressable, discard extent on the underlying device.
- *
- * discard-granularity
- * Values: <uint32_t>
- * Default Value: <"sector-size">
- * Notes: 4
- *
- * The size, in bytes, of the individually addressable discard extents
- * of the underlying device.
- *
- * discard-secure
- * Values: 0/1 (boolean)
- * Default Value: 0
- * Notes: 10
- *
- * A value of "1" indicates that the backend can process BLKIF_OP_DISCARD
- * requests with the BLKIF_DISCARD_SECURE flag set.
- *
- * info
- * Values: <uint32_t> (bitmap)
- *
- * A collection of bit flags describing attributes of the backing
- * device. The VDISK_* macros define the meaning of each bit
- * location.
- *
- * sector-size
- * Values: <uint32_t>
- *
- * The logical sector size, in bytes, of the backend device.
- *
- * physical-sector-size
- * Values: <uint32_t>
- *
- * The physical sector size, in bytes, of the backend device.
- *
- * sectors
- * Values: <uint64_t>
- *
- * The size of the backend device, expressed in units of its logical
- * sector size ("sector-size").
- *
- *****************************************************************************
- * Frontend XenBus Nodes
- *****************************************************************************
- *
- *----------------------- Request Transport Parameters -----------------------
- *
- * event-channel
- * Values: <uint32_t>
- *
- * The identifier of the Xen event channel used to signal activity
- * in the ring buffer.
- *
- * ring-ref
- * Values: <uint32_t>
- * Notes: 6
- *
- * The Xen grant reference granting permission for the backend to map
- * the sole page in a single page sized ring buffer.
- *
- * ring-ref%u
- * Values: <uint32_t>
- * Notes: 6
- *
- * For a frontend providing a multi-page ring, a "number of ring pages"
- * sized list of nodes, each containing a Xen grant reference granting
- * permission for the backend to map the page of the ring located
- * at page index "%u". Page indexes are zero based.
- *
- * protocol
- * Values: string (XEN_IO_PROTO_ABI_*)
- * Default Value: XEN_IO_PROTO_ABI_NATIVE
- *
- * The machine ABI rules governing the format of all ring request and
- * response structures.
- *
- * ring-page-order
- * Values: <uint32_t>
- * Default Value: 0
- * Maximum Value: MAX(ffs(max-ring-pages) - 1, max-ring-page-order)
- * Notes: 1, 3
- *
- * The size of the frontend allocated request ring buffer in units
- * of lb(machine pages). (e.g. 0 == 1 page, 1 = 2 pages, 2 == 4 pages,
- * etc.).
- *
- * num-ring-pages
- * Values: <uint32_t>
- * Default Value: 1
- * Maximum Value: MAX(max-ring-pages,(0x1 << max-ring-page-order))
- * Notes: DEPRECATED, 2, 3
- *
- * The size of the frontend allocated request ring buffer in units of
- * machine pages. The value must be a power of 2.
- *
- * feature-persistent
- * Values: 0/1 (boolean)
- * Default Value: 0
- * Notes: 7, 8, 9
- *
- * A value of "1" indicates that the frontend will reuse the same grants
- * for all transactions, allowing the backend to map them with write
- * access (even when it should be read-only). If the frontend hits the
- * maximum number of allowed persistently mapped grants, it can fallback
- * to non persistent mode. This will cause a performance degradation,
- * since the the backend driver will still try to map those grants
- * persistently. Since the persistent grants protocol is compatible with
- * the previous protocol, a frontend driver can choose to work in
- * persistent mode even when the backend doesn't support it.
- *
- * It is recommended that the frontend driver stores the persistently
- * mapped grants in a LIFO queue, so a subset of all persistently mapped
- * grants gets used commonly. This is done in case the backend driver
- * decides to limit the maximum number of persistently mapped grants
- * to a value less than RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST.
- *
- *------------------------- Virtual Device Properties -------------------------
- *
- * device-type
- * Values: "disk", "cdrom", "floppy", etc.
- *
- * virtual-device
- * Values: <uint32_t>
- *
- * A value indicating the physical device to virtualize within the
- * frontend's domain. (e.g. "The first ATA disk", "The third SCSI
- * disk", etc.)
- *
- * See docs/misc/vbd-interface.txt for details on the format of this
- * value.
- *
- * Notes
- * -----
- * (1) Multi-page ring buffer scheme first developed in the Citrix XenServer
- * PV drivers.
- * (2) Multi-page ring buffer scheme first used in some RedHat distributions
- * including a distribution deployed on certain nodes of the Amazon
- * EC2 cluster.
- * (3) Support for multi-page ring buffers was implemented independently,
- * in slightly different forms, by both Citrix and RedHat/Amazon.
- * For full interoperability, block front and backends should publish
- * identical ring parameters, adjusted for unit differences, to the
- * XenStore nodes used in both schemes.
- * (4) Devices that support discard functionality may internally allocate space
- * (discardable extents) in units that are larger than the exported logical
- * block size. If the backing device has such discardable extents the
- * backend should provide both discard-granularity and discard-alignment.
- * Providing just one of the two may be considered an error by the frontend.
- * Backends supporting discard should include discard-granularity and
- * discard-alignment even if it supports discarding individual sectors.
- * Frontends should assume discard-alignment == 0 and discard-granularity
- * == sector size if these keys are missing.
- * (5) The discard-alignment parameter allows a physical device to be
- * partitioned into virtual devices that do not necessarily begin or
- * end on a discardable extent boundary.
- * (6) When there is only a single page allocated to the request ring,
- * 'ring-ref' is used to communicate the grant reference for this
- * page to the backend. When using a multi-page ring, the 'ring-ref'
- * node is not created. Instead 'ring-ref0' - 'ring-refN' are used.
- * (7) When using persistent grants data has to be copied from/to the page
- * where the grant is currently mapped. The overhead of doing this copy
- * however doesn't suppress the speed improvement of not having to unmap
- * the grants.
- * (8) The frontend driver has to allow the backend driver to map all grants
- * with write access, even when they should be mapped read-only, since
- * further requests may reuse these grants and require write permissions.
- * (9) Linux implementation doesn't have a limit on the maximum number of
- * grants that can be persistently mapped in the frontend driver, but
- * due to the frontent driver implementation it should never be bigger
- * than RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST.
- *(10) The discard-secure property may be present and will be set to 1 if the
- * backing device supports secure discard.
- */
-
-/*
- * STATE DIAGRAMS
- *
- *****************************************************************************
- * Startup *
- *****************************************************************************
- *
- * Tool stack creates front and back nodes with state XenbusStateInitialising.
- *
- * Front Back
- * ================================= =====================================
- * XenbusStateInitialising XenbusStateInitialising
- * o Query virtual device o Query backend device identification
- * properties. data.
- * o Setup OS device instance. o Open and validate backend device.
- * o Publish backend features and
- * transport parameters.
- * |
- * |
- * V
- * XenbusStateInitWait
- *
- * o Query backend features and
- * transport parameters.
- * o Allocate and initialize the
- * request ring.
- * o Publish transport parameters
- * that will be in effect during
- * this connection.
- * |
- * |
- * V
- * XenbusStateInitialised
- *
- * o Query frontend transport parameters.
- * o Connect to the request ring and
- * event channel.
- * o Publish backend device properties.
- * |
- * |
- * V
- * XenbusStateConnected
- *
- * o Query backend device properties.
- * o Finalize OS virtual device
- * instance.
- * |
- * |
- * V
- * XenbusStateConnected
- *
- * Note: Drivers that do not support any optional features, or the negotiation
- * of transport parameters, can skip certain states in the state machine:
- *
- * o A frontend may transition to XenbusStateInitialised without
- * waiting for the backend to enter XenbusStateInitWait. In this
- * case, default transport parameters are in effect and any
- * transport parameters published by the frontend must contain
- * their default values.
- *
- * o A backend may transition to XenbusStateInitialised, bypassing
- * XenbusStateInitWait, without waiting for the frontend to first
- * enter the XenbusStateInitialised state. In this case, default
- * transport parameters are in effect and any transport parameters
- * published by the backend must contain their default values.
- *
- * Drivers that support optional features and/or transport parameter
- * negotiation must tolerate these additional state transition paths.
- * In general this means performing the work of any skipped state
- * transition, if it has not already been performed, in addition to the
- * work associated with entry into the current state.
- */
-
-/*
- * REQUEST CODES.
- */
-#define BLKIF_OP_READ 0
-#define BLKIF_OP_WRITE 1
-/*
- * All writes issued prior to a request with the BLKIF_OP_WRITE_BARRIER
- * operation code ("barrier request") must be completed prior to the
- * execution of the barrier request. All writes issued after the barrier
- * request must not execute until after the completion of the barrier request.
- *
- * Optional. See "feature-barrier" XenBus node documentation above.
- */
-#define BLKIF_OP_WRITE_BARRIER 2
-/*
- * Commit any uncommitted contents of the backing device's volatile cache
- * to stable storage.
- *
- * Optional. See "feature-flush-cache" XenBus node documentation above.
- */
-#define BLKIF_OP_FLUSH_DISKCACHE 3
-/*
- * Used in SLES sources for device specific command packet
- * contained within the request. Reserved for that purpose.
- */
-#define BLKIF_OP_RESERVED_1 4
-/*
- * Indicate to the backend device that a region of storage is no longer in
- * use, and may be discarded at any time without impact to the client. If
- * the BLKIF_DISCARD_SECURE flag is set on the request, all copies of the
- * discarded region on the device must be rendered unrecoverable before the
- * command returns.
- *
- * This operation is analogous to performing a trim (ATA) or unamp (SCSI),
- * command on a native device.
- *
- * More information about trim/unmap operations can be found at:
- * http://t13.org/Documents/UploadedDocuments/docs2008/
- * e07154r6-Data_Set_Management_Proposal_for_ATA-ACS2.doc
- * http://www.seagate.com/staticfiles/support/disc/manuals/
- * Interface%20manuals/100293068c.pdf
- *
- * Optional. See "feature-discard", "discard-alignment",
- * "discard-granularity", and "discard-secure" in the XenBus node
- * documentation above.
- */
-#define BLKIF_OP_DISCARD 5
-
-/*
- * Recognized if "feature-max-indirect-segments" in present in the backend
- * xenbus info. The "feature-max-indirect-segments" node contains the maximum
- * number of segments allowed by the backend per request. If the node is
- * present, the frontend might use blkif_request_indirect structs in order to
- * issue requests with more than BLKIF_MAX_SEGMENTS_PER_REQUEST (11). The
- * maximum number of indirect segments is fixed by the backend, but the
- * frontend can issue requests with any number of indirect segments as long as
- * it's less than the number provided by the backend. The indirect_grefs field
- * in blkif_request_indirect should be filled by the frontend with the
- * grant references of the pages that are holding the indirect segments.
- * These pages are filled with an array of blkif_request_segment that hold the
- * information about the segments. The number of indirect pages to use is
- * determined by the number of segments an indirect request contains. Every
- * indirect page can contain a maximum of
- * (PAGE_SIZE / sizeof(struct blkif_request_segment)) segments, so to
- * calculate the number of indirect pages to use we have to do
- * ceil(indirect_segments / (PAGE_SIZE / sizeof(struct blkif_request_segment))).
- *
- * If a backend does not recognize BLKIF_OP_INDIRECT, it should *not*
- * create the "feature-max-indirect-segments" node!
- */
-#define BLKIF_OP_INDIRECT 6
-
-/*
- * Maximum scatter/gather segments per request.
- * This is carefully chosen so that sizeof(blkif_ring_t) <= PAGE_SIZE.
- * NB. This could be 12 if the ring indexes weren't stored in the same page.
- */
-#define BLKIF_MAX_SEGMENTS_PER_REQUEST 11
-
-/*
- * Maximum number of indirect pages to use per request.
- */
-#define BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST 8
-
-/*
- * NB. first_sect and last_sect in blkif_request_segment, as well as
- * sector_number in blkif_request, are always expressed in 512-byte units.
- * However they must be properly aligned to the real sector size of the
- * physical disk, which is reported in the "physical-sector-size" node in
- * the backend xenbus info. Also the xenbus "sectors" node is expressed in
- * 512-byte units.
- */
-struct blkif_request_segment {
- grant_ref_t gref; /* reference to I/O buffer frame */
- /* @first_sect: first sector in frame to transfer (inclusive). */
- /* @last_sect: last sector in frame to transfer (inclusive). */
- uint8_t first_sect, last_sect;
-};
-
-/*
- * Starting ring element for any I/O request.
- */
-struct blkif_request {
- uint8_t operation; /* BLKIF_OP_??? */
- uint8_t nr_segments; /* number of segments */
- blkif_vdev_t handle; /* only for read/write requests */
- uint64_t id; /* private guest value, echoed in resp */
- blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
- struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-};
-typedef struct blkif_request blkif_request_t;
-
-/*
- * Cast to this structure when blkif_request.operation == BLKIF_OP_DISCARD
- * sizeof(struct blkif_request_discard) <= sizeof(struct blkif_request)
- */
-struct blkif_request_discard {
- uint8_t operation; /* BLKIF_OP_DISCARD */
- uint8_t flag; /* BLKIF_DISCARD_SECURE or zero */
-#define BLKIF_DISCARD_SECURE (1<<0) /* ignored if discard-secure=0 */
- blkif_vdev_t handle; /* same as for read/write requests */
- uint64_t id; /* private guest value, echoed in resp */
- blkif_sector_t sector_number;/* start sector idx on disk */
- uint64_t nr_sectors; /* number of contiguous sectors to discard*/
-};
-typedef struct blkif_request_discard blkif_request_discard_t;
-
-struct blkif_request_indirect {
- uint8_t operation; /* BLKIF_OP_INDIRECT */
- uint8_t indirect_op; /* BLKIF_OP_{READ/WRITE} */
- uint16_t nr_segments; /* number of segments */
- uint64_t id; /* private guest value, echoed in resp */
- blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
- blkif_vdev_t handle; /* same as for read/write requests */
- grant_ref_t indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
-#ifdef __i386__
- uint64_t pad; /* Make it 64 byte aligned on i386 */
-#endif
-};
-typedef struct blkif_request_indirect blkif_request_indirect_t;
-
-struct blkif_response {
- uint64_t id; /* copied from request */
- uint8_t operation; /* copied from request */
- int16_t status; /* BLKIF_RSP_??? */
-};
-typedef struct blkif_response blkif_response_t;
-
-/*
- * STATUS RETURN CODES.
- */
- /* Operation not supported (only happens on barrier writes). */
-#define BLKIF_RSP_EOPNOTSUPP -2
- /* Operation failed for some unspecified reason (-EIO). */
-#define BLKIF_RSP_ERROR -1
- /* Operation completed successfully. */
-#define BLKIF_RSP_OKAY 0
-
-/*
- * Generate blkif ring structures and types.
- */
-DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response);
-
-#define VDISK_CDROM 0x1
-#define VDISK_REMOVABLE 0x2
-#define VDISK_READONLY 0x4
-
-#endif /* __XEN_PUBLIC_IO_BLKIF_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * console.h
- *
- * Console I/O interface for Xen guest OSes.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2005, Keir Fraser
- */
-
-#ifndef __XEN_PUBLIC_IO_CONSOLE_H__
-#define __XEN_PUBLIC_IO_CONSOLE_H__
-
-typedef uint32_t XENCONS_RING_IDX;
-
-#define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1))
-
-struct xencons_interface {
- char in[1024];
- char out[2048];
- XENCONS_RING_IDX in_cons, in_prod;
- XENCONS_RING_IDX out_cons, out_prod;
-};
-
-#endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/*
- * fbif.h -- Xen virtual frame buffer device
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
- * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
- */
-
-#ifndef __XEN_PUBLIC_IO_FBIF_H__
-#define __XEN_PUBLIC_IO_FBIF_H__
-
-/* Out events (frontend -> backend) */
-
-/*
- * Out events may be sent only when requested by backend, and receipt
- * of an unknown out event is an error.
- */
-
-/* Event type 1 currently not used */
-/*
- * Framebuffer update notification event
- * Capable frontend sets feature-update in xenstore.
- * Backend requests it by setting request-update in xenstore.
- */
-#define XENFB_TYPE_UPDATE 2
-
-struct xenfb_update
-{
- uint8_t type; /* XENFB_TYPE_UPDATE */
- int32_t x; /* source x */
- int32_t y; /* source y */
- int32_t width; /* rect width */
- int32_t height; /* rect height */
-};
-
-/*
- * Framebuffer resize notification event
- * Capable backend sets feature-resize in xenstore.
- */
-#define XENFB_TYPE_RESIZE 3
-
-struct xenfb_resize
-{
- uint8_t type; /* XENFB_TYPE_RESIZE */
- int32_t width; /* width in pixels */
- int32_t height; /* height in pixels */
- int32_t stride; /* stride in bytes */
- int32_t depth; /* depth in bits */
- int32_t offset; /* offset of the framebuffer in bytes */
-};
-
-#define XENFB_OUT_EVENT_SIZE 40
-
-union xenfb_out_event
-{
- uint8_t type;
- struct xenfb_update update;
- struct xenfb_resize resize;
- char pad[XENFB_OUT_EVENT_SIZE];
-};
-
-/* In events (backend -> frontend) */
-
-/*
- * Frontends should ignore unknown in events.
- */
-
-/*
- * Framebuffer refresh period advice
- * Backend sends it to advise the frontend their preferred period of
- * refresh. Frontends that keep the framebuffer constantly up-to-date
- * just ignore it. Frontends that use the advice should immediately
- * refresh the framebuffer (and send an update notification event if
- * those have been requested), then use the update frequency to guide
- * their periodical refreshs.
- */
-#define XENFB_TYPE_REFRESH_PERIOD 1
-#define XENFB_NO_REFRESH 0
-
-struct xenfb_refresh_period
-{
- uint8_t type; /* XENFB_TYPE_UPDATE_PERIOD */
- uint32_t period; /* period of refresh, in ms,
- * XENFB_NO_REFRESH if no refresh is needed */
-};
-
-#define XENFB_IN_EVENT_SIZE 40
-
-union xenfb_in_event
-{
- uint8_t type;
- struct xenfb_refresh_period refresh_period;
- char pad[XENFB_IN_EVENT_SIZE];
-};
-
-/* shared page */
-
-#define XENFB_IN_RING_SIZE 1024
-#define XENFB_IN_RING_LEN (XENFB_IN_RING_SIZE / XENFB_IN_EVENT_SIZE)
-#define XENFB_IN_RING_OFFS 1024
-#define XENFB_IN_RING(page) \
- ((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS))
-#define XENFB_IN_RING_REF(page, idx) \
- (XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN])
-
-#define XENFB_OUT_RING_SIZE 2048
-#define XENFB_OUT_RING_LEN (XENFB_OUT_RING_SIZE / XENFB_OUT_EVENT_SIZE)
-#define XENFB_OUT_RING_OFFS (XENFB_IN_RING_OFFS + XENFB_IN_RING_SIZE)
-#define XENFB_OUT_RING(page) \
- ((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS))
-#define XENFB_OUT_RING_REF(page, idx) \
- (XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN])
-
-struct xenfb_page
-{
- uint32_t in_cons, in_prod;
- uint32_t out_cons, out_prod;
-
- int32_t width; /* the width of the framebuffer (in pixels) */
- int32_t height; /* the height of the framebuffer (in pixels) */
- uint32_t line_length; /* the length of a row of pixels (in bytes) */
- uint32_t mem_length; /* the length of the framebuffer (in bytes) */
- uint8_t depth; /* the depth of a pixel (in bits) */
-
- /*
- * Framebuffer page directory
- *
- * Each directory page holds PAGE_SIZE / sizeof(*pd)
- * framebuffer pages, and can thus map up to PAGE_SIZE *
- * PAGE_SIZE / sizeof(*pd) bytes. With PAGE_SIZE == 4096 and
- * sizeof(unsigned long) == 4/8, that's 4 Megs 32 bit and 2 Megs
- * 64 bit. 256 directories give enough room for a 512 Meg
- * framebuffer with a max resolution of 12,800x10,240. Should
- * be enough for a while with room leftover for expansion.
- */
- unsigned long pd[256];
-};
-
-/*
- * Wart: xenkbd needs to know default resolution. Put it here until a
- * better solution is found, but don't leak it to the backend.
- */
-#ifdef __KERNEL__
-#define XENFB_WIDTH 800
-#define XENFB_HEIGHT 600
-#define XENFB_DEPTH 32
-#endif
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * fsif.h
- *
- * Interface to FS level split device drivers.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2007, Grzegorz Milos, <gm281@cam.ac.uk>.
- */
-
-#ifndef __XEN_PUBLIC_IO_FSIF_H__
-#define __XEN_PUBLIC_IO_FSIF_H__
-
-#include "ring.h"
-#include "../grant_table.h"
-
-#define REQ_FILE_OPEN 1
-#define REQ_FILE_CLOSE 2
-#define REQ_FILE_READ 3
-#define REQ_FILE_WRITE 4
-#define REQ_STAT 5
-#define REQ_FILE_TRUNCATE 6
-#define REQ_REMOVE 7
-#define REQ_RENAME 8
-#define REQ_CREATE 9
-#define REQ_DIR_LIST 10
-#define REQ_CHMOD 11
-#define REQ_FS_SPACE 12
-#define REQ_FILE_SYNC 13
-
-struct fsif_open_request {
- grant_ref_t gref;
-};
-
-struct fsif_close_request {
- uint32_t fd;
-};
-
-struct fsif_read_request {
- uint32_t fd;
- int32_t pad;
- uint64_t len;
- uint64_t offset;
- grant_ref_t grefs[1]; /* Variable length */
-};
-
-struct fsif_write_request {
- uint32_t fd;
- int32_t pad;
- uint64_t len;
- uint64_t offset;
- grant_ref_t grefs[1]; /* Variable length */
-};
-
-struct fsif_stat_request {
- uint32_t fd;
-};
-
-/* This structure is a copy of some fields from stat structure, returned
- * via the ring. */
-struct fsif_stat_response {
- int32_t stat_mode;
- uint32_t stat_uid;
- uint32_t stat_gid;
- int32_t stat_ret;
- int64_t stat_size;
- int64_t stat_atime;
- int64_t stat_mtime;
- int64_t stat_ctime;
-};
-
-struct fsif_truncate_request {
- uint32_t fd;
- int32_t pad;
- int64_t length;
-};
-
-struct fsif_remove_request {
- grant_ref_t gref;
-};
-
-struct fsif_rename_request {
- uint16_t old_name_offset;
- uint16_t new_name_offset;
- grant_ref_t gref;
-};
-
-struct fsif_create_request {
- int8_t directory;
- int8_t pad;
- int16_t pad2;
- int32_t mode;
- grant_ref_t gref;
-};
-
-struct fsif_list_request {
- uint32_t offset;
- grant_ref_t gref;
-};
-
-#define NR_FILES_SHIFT 0
-#define NR_FILES_SIZE 16 /* 16 bits for the number of files mask */
-#define NR_FILES_MASK (((1ULL << NR_FILES_SIZE) - 1) << NR_FILES_SHIFT)
-#define ERROR_SIZE 32 /* 32 bits for the error mask */
-#define ERROR_SHIFT (NR_FILES_SIZE + NR_FILES_SHIFT)
-#define ERROR_MASK (((1ULL << ERROR_SIZE) - 1) << ERROR_SHIFT)
-#define HAS_MORE_SHIFT (ERROR_SHIFT + ERROR_SIZE)
-#define HAS_MORE_FLAG (1ULL << HAS_MORE_SHIFT)
-
-struct fsif_chmod_request {
- uint32_t fd;
- int32_t mode;
-};
-
-struct fsif_space_request {
- grant_ref_t gref;
-};
-
-struct fsif_sync_request {
- uint32_t fd;
-};
-
-
-/* FS operation request */
-struct fsif_request {
- uint8_t type; /* Type of the request */
- uint8_t pad;
- uint16_t id; /* Request ID, copied to the response */
- uint32_t pad2;
- union {
- struct fsif_open_request fopen;
- struct fsif_close_request fclose;
- struct fsif_read_request fread;
- struct fsif_write_request fwrite;
- struct fsif_stat_request fstat;
- struct fsif_truncate_request ftruncate;
- struct fsif_remove_request fremove;
- struct fsif_rename_request frename;
- struct fsif_create_request fcreate;
- struct fsif_list_request flist;
- struct fsif_chmod_request fchmod;
- struct fsif_space_request fspace;
- struct fsif_sync_request fsync;
- } u;
-};
-typedef struct fsif_request fsif_request_t;
-
-/* FS operation response */
-struct fsif_response {
- uint16_t id;
- uint16_t pad1;
- uint32_t pad2;
- union {
- uint64_t ret_val;
- struct fsif_stat_response fstat;
- } u;
-};
-
-typedef struct fsif_response fsif_response_t;
-
-#define FSIF_RING_ENTRY_SIZE 64
-
-#define FSIF_NR_READ_GNTS ((FSIF_RING_ENTRY_SIZE - sizeof(struct fsif_read_request)) / \
- sizeof(grant_ref_t) + 1)
-#define FSIF_NR_WRITE_GNTS ((FSIF_RING_ENTRY_SIZE - sizeof(struct fsif_write_request)) / \
- sizeof(grant_ref_t) + 1)
-
-DEFINE_RING_TYPES(fsif, struct fsif_request, struct fsif_response);
-
-#define STATE_INITIALISED "init"
-#define STATE_READY "ready"
-#define STATE_CLOSING "closing"
-#define STATE_CLOSED "closed"
-
-
-#endif
+++ /dev/null
-/*
- * kbdif.h -- Xen virtual keyboard/mouse
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
- * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
- */
-
-#ifndef __XEN_PUBLIC_IO_KBDIF_H__
-#define __XEN_PUBLIC_IO_KBDIF_H__
-
-/* In events (backend -> frontend) */
-
-/*
- * Frontends should ignore unknown in events.
- */
-
-/* Pointer movement event */
-#define XENKBD_TYPE_MOTION 1
-/* Event type 2 currently not used */
-/* Key event (includes pointer buttons) */
-#define XENKBD_TYPE_KEY 3
-/*
- * Pointer position event
- * Capable backend sets feature-abs-pointer in xenstore.
- * Frontend requests ot instead of XENKBD_TYPE_MOTION by setting
- * request-abs-update in xenstore.
- */
-#define XENKBD_TYPE_POS 4
-
-struct xenkbd_motion
-{
- uint8_t type; /* XENKBD_TYPE_MOTION */
- int32_t rel_x; /* relative X motion */
- int32_t rel_y; /* relative Y motion */
- int32_t rel_z; /* relative Z motion (wheel) */
-};
-
-struct xenkbd_key
-{
- uint8_t type; /* XENKBD_TYPE_KEY */
- uint8_t pressed; /* 1 if pressed; 0 otherwise */
- uint32_t keycode; /* KEY_* from linux/input.h */
-};
-
-struct xenkbd_position
-{
- uint8_t type; /* XENKBD_TYPE_POS */
- int32_t abs_x; /* absolute X position (in FB pixels) */
- int32_t abs_y; /* absolute Y position (in FB pixels) */
- int32_t rel_z; /* relative Z motion (wheel) */
-};
-
-#define XENKBD_IN_EVENT_SIZE 40
-
-union xenkbd_in_event
-{
- uint8_t type;
- struct xenkbd_motion motion;
- struct xenkbd_key key;
- struct xenkbd_position pos;
- char pad[XENKBD_IN_EVENT_SIZE];
-};
-
-/* Out events (frontend -> backend) */
-
-/*
- * Out events may be sent only when requested by backend, and receipt
- * of an unknown out event is an error.
- * No out events currently defined.
- */
-
-#define XENKBD_OUT_EVENT_SIZE 40
-
-union xenkbd_out_event
-{
- uint8_t type;
- char pad[XENKBD_OUT_EVENT_SIZE];
-};
-
-/* shared page */
-
-#define XENKBD_IN_RING_SIZE 2048
-#define XENKBD_IN_RING_LEN (XENKBD_IN_RING_SIZE / XENKBD_IN_EVENT_SIZE)
-#define XENKBD_IN_RING_OFFS 1024
-#define XENKBD_IN_RING(page) \
- ((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS))
-#define XENKBD_IN_RING_REF(page, idx) \
- (XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN])
-
-#define XENKBD_OUT_RING_SIZE 1024
-#define XENKBD_OUT_RING_LEN (XENKBD_OUT_RING_SIZE / XENKBD_OUT_EVENT_SIZE)
-#define XENKBD_OUT_RING_OFFS (XENKBD_IN_RING_OFFS + XENKBD_IN_RING_SIZE)
-#define XENKBD_OUT_RING(page) \
- ((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS))
-#define XENKBD_OUT_RING_REF(page, idx) \
- (XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN])
-
-struct xenkbd_page
-{
- uint32_t in_cons, in_prod;
- uint32_t out_cons, out_prod;
-};
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/**
- * @file
- * @section AUTHORS
- *
- * Copyright (C) 2010 Rafal Wojtczuk <rafal@invisiblethingslab.com>
- *
- * Authors:
- * Rafal Wojtczuk <rafal@invisiblethingslab.com>
- * Daniel De Graaf <dgdegra@tycho.nsa.gov>
- *
- * @section LICENSE
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * @section DESCRIPTION
- *
- * Originally borrowed from the Qubes OS Project, http://www.qubes-os.org,
- * this code has been substantially rewritten to use the gntdev and gntalloc
- * devices instead of raw MFNs and map_foreign_range.
- *
- * This is a library for inter-domain communication. A standard Xen ring
- * buffer is used, with a datagram-based interface built on top. The grant
- * reference and event channels are shared in XenStore under a user-specified
- * path.
- *
- * The ring.h macros define an asymmetric interface to a shared data structure
- * that assumes all rings reside in a single contiguous memory space. This is
- * not suitable for vchan because the interface to the ring is symmetric except
- * for the setup. Unlike the producer-consumer rings defined in ring.h, the
- * size of the rings used in vchan are determined at execution time instead of
- * compile time, so the macros in ring.h cannot be used to access the rings.
- */
-
-#include <stdint.h>
-#include <sys/types.h>
-
-struct ring_shared {
- uint32_t cons, prod;
-};
-
-#define VCHAN_NOTIFY_WRITE 0x1
-#define VCHAN_NOTIFY_READ 0x2
-
-/**
- * vchan_interface: primary shared data structure
- */
-struct vchan_interface {
- /**
- * Standard consumer/producer interface, one pair per buffer
- * left is client write, server read
- * right is client read, server write
- */
- struct ring_shared left, right;
- /**
- * size of the rings, which determines their location
- * 10 - at offset 1024 in ring's page
- * 11 - at offset 2048 in ring's page
- * 12+ - uses 2^(N-12) grants to describe the multi-page ring
- * These should remain constant once the page is shared.
- * Only one of the two orders can be 10 (or 11).
- */
- uint16_t left_order, right_order;
- /**
- * Shutdown detection:
- * 0: client (or server) has exited
- * 1: client (or server) is connected
- * 2: client has not yet connected
- */
- uint8_t cli_live, srv_live;
- /**
- * Notification bits:
- * VCHAN_NOTIFY_WRITE: send notify when data is written
- * VCHAN_NOTIFY_READ: send notify when data is read (consumed)
- * cli_notify is used for the client to inform the server of its action
- */
- uint8_t cli_notify, srv_notify;
- /**
- * Grant list: ordering is left, right. Must not extend into actual ring
- * or grow beyond the end of the initial shared page.
- * These should remain constant once the page is shared, to allow
- * for possible remapping by a client that restarts.
- */
- uint32_t grants[0];
-};
-
+++ /dev/null
-/******************************************************************************
- * netif.h
- *
- * Unified network-device I/O interface for Xen guest OSes.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2003-2004, Keir Fraser
- */
-
-#ifndef __XEN_PUBLIC_IO_NETIF_H__
-#define __XEN_PUBLIC_IO_NETIF_H__
-
-#include "ring.h"
-#include "../grant_table.h"
-
-/*
- * Older implementation of Xen network frontend / backend has an
- * implicit dependency on the MAX_SKB_FRAGS as the maximum number of
- * ring slots a skb can use. Netfront / netback may not work as
- * expected when frontend and backend have different MAX_SKB_FRAGS.
- *
- * A better approach is to add mechanism for netfront / netback to
- * negotiate this value. However we cannot fix all possible
- * frontends, so we need to define a value which states the minimum
- * slots backend must support.
- *
- * The minimum value derives from older Linux kernel's MAX_SKB_FRAGS
- * (18), which is proved to work with most frontends. Any new backend
- * which doesn't negotiate with frontend should expect frontend to
- * send a valid packet using slots up to this value.
- */
-#define XEN_NETIF_NR_SLOTS_MIN 18
-
-/*
- * Notifications after enqueuing any type of message should be conditional on
- * the appropriate req_event or rsp_event field in the shared ring.
- * If the client sends notification for rx requests then it should specify
- * feature 'feature-rx-notify' via xenbus. Otherwise the backend will assume
- * that it cannot safely queue packets (as it may not be kicked to send them).
- */
-
-/*
- * "feature-split-event-channels" is introduced to separate guest TX
- * and RX notification. Backend either doesn't support this feature or
- * advertises it via xenstore as 0 (disabled) or 1 (enabled).
- *
- * To make use of this feature, frontend should allocate two event
- * channels for TX and RX, advertise them to backend as
- * "event-channel-tx" and "event-channel-rx" respectively. If frontend
- * doesn't want to use this feature, it just writes "event-channel"
- * node as before.
- */
-
-/*
- * Multiple transmit and receive queues:
- * If supported, the backend will write the key "multi-queue-max-queues" to
- * the directory for that vif, and set its value to the maximum supported
- * number of queues.
- * Frontends that are aware of this feature and wish to use it can write the
- * key "multi-queue-num-queues", set to the number they wish to use, which
- * must be greater than zero, and no more than the value reported by the backend
- * in "multi-queue-max-queues".
- *
- * Queues replicate the shared rings and event channels.
- * "feature-split-event-channels" may optionally be used when using
- * multiple queues, but is not mandatory.
- *
- * Each queue consists of one shared ring pair, i.e. there must be the same
- * number of tx and rx rings.
- *
- * For frontends requesting just one queue, the usual event-channel and
- * ring-ref keys are written as before, simplifying the backend processing
- * to avoid distinguishing between a frontend that doesn't understand the
- * multi-queue feature, and one that does, but requested only one queue.
- *
- * Frontends requesting two or more queues must not write the toplevel
- * event-channel (or event-channel-{tx,rx}) and {tx,rx}-ring-ref keys,
- * instead writing those keys under sub-keys having the name "queue-N" where
- * N is the integer ID of the queue for which those keys belong. Queues
- * are indexed from zero. For example, a frontend with two queues and split
- * event channels must write the following set of queue-related keys:
- *
- * /local/domain/1/device/vif/0/multi-queue-num-queues = "2"
- * /local/domain/1/device/vif/0/queue-0 = ""
- * /local/domain/1/device/vif/0/queue-0/tx-ring-ref = "<ring-ref-tx0>"
- * /local/domain/1/device/vif/0/queue-0/rx-ring-ref = "<ring-ref-rx0>"
- * /local/domain/1/device/vif/0/queue-0/event-channel-tx = "<evtchn-tx0>"
- * /local/domain/1/device/vif/0/queue-0/event-channel-rx = "<evtchn-rx0>"
- * /local/domain/1/device/vif/0/queue-1 = ""
- * /local/domain/1/device/vif/0/queue-1/tx-ring-ref = "<ring-ref-tx1>"
- * /local/domain/1/device/vif/0/queue-1/rx-ring-ref = "<ring-ref-rx1"
- * /local/domain/1/device/vif/0/queue-1/event-channel-tx = "<evtchn-tx1>"
- * /local/domain/1/device/vif/0/queue-1/event-channel-rx = "<evtchn-rx1>"
- *
- * If there is any inconsistency in the XenStore data, the backend may
- * choose not to connect any queues, instead treating the request as an
- * error. This includes scenarios where more (or fewer) queues were
- * requested than the frontend provided details for.
- *
- * Mapping of packets to queues is considered to be a function of the
- * transmitting system (backend or frontend) and is not negotiated
- * between the two. Guests are free to transmit packets on any queue
- * they choose, provided it has been set up correctly. Guests must be
- * prepared to receive packets on any queue they have requested be set up.
- */
-
-/*
- * "feature-no-csum-offload" should be used to turn IPv4 TCP/UDP checksum
- * offload off or on. If it is missing then the feature is assumed to be on.
- * "feature-ipv6-csum-offload" should be used to turn IPv6 TCP/UDP checksum
- * offload on or off. If it is missing then the feature is assumed to be off.
- */
-
-/*
- * "feature-gso-tcpv4" and "feature-gso-tcpv6" advertise the capability to
- * handle large TCP packets (in IPv4 or IPv6 form respectively). Neither
- * frontends nor backends are assumed to be capable unless the flags are
- * present.
- */
-
-/*
- * This is the 'wire' format for packets:
- * Request 1: netif_tx_request -- NETTXF_* (any flags)
- * [Request 2: netif_tx_extra] (only if request 1 has NETTXF_extra_info)
- * [Request 3: netif_tx_extra] (only if request 2 has XEN_NETIF_EXTRA_MORE)
- * Request 4: netif_tx_request -- NETTXF_more_data
- * Request 5: netif_tx_request -- NETTXF_more_data
- * ...
- * Request N: netif_tx_request -- 0
- */
-
-/* Protocol checksum field is blank in the packet (hardware offload)? */
-#define _NETTXF_csum_blank (0)
-#define NETTXF_csum_blank (1U<<_NETTXF_csum_blank)
-
-/* Packet data has been validated against protocol checksum. */
-#define _NETTXF_data_validated (1)
-#define NETTXF_data_validated (1U<<_NETTXF_data_validated)
-
-/* Packet continues in the next request descriptor. */
-#define _NETTXF_more_data (2)
-#define NETTXF_more_data (1U<<_NETTXF_more_data)
-
-/* Packet to be followed by extra descriptor(s). */
-#define _NETTXF_extra_info (3)
-#define NETTXF_extra_info (1U<<_NETTXF_extra_info)
-
-#define XEN_NETIF_MAX_TX_SIZE 0xFFFF
-struct netif_tx_request {
- grant_ref_t gref; /* Reference to buffer page */
- uint16_t offset; /* Offset within buffer page */
- uint16_t flags; /* NETTXF_* */
- uint16_t id; /* Echoed in response message. */
- uint16_t size; /* Packet size in bytes. */
-};
-typedef struct netif_tx_request netif_tx_request_t;
-
-/* Types of netif_extra_info descriptors. */
-#define XEN_NETIF_EXTRA_TYPE_NONE (0) /* Never used - invalid */
-#define XEN_NETIF_EXTRA_TYPE_GSO (1) /* u.gso */
-#define XEN_NETIF_EXTRA_TYPE_MCAST_ADD (2) /* u.mcast */
-#define XEN_NETIF_EXTRA_TYPE_MCAST_DEL (3) /* u.mcast */
-#define XEN_NETIF_EXTRA_TYPE_MAX (4)
-
-/* netif_extra_info flags. */
-#define _XEN_NETIF_EXTRA_FLAG_MORE (0)
-#define XEN_NETIF_EXTRA_FLAG_MORE (1U<<_XEN_NETIF_EXTRA_FLAG_MORE)
-
-/* GSO types */
-#define XEN_NETIF_GSO_TYPE_NONE (0)
-#define XEN_NETIF_GSO_TYPE_TCPV4 (1)
-#define XEN_NETIF_GSO_TYPE_TCPV6 (2)
-
-/*
- * This structure needs to fit within both netif_tx_request and
- * netif_rx_response for compatibility.
- */
-struct netif_extra_info {
- uint8_t type; /* XEN_NETIF_EXTRA_TYPE_* */
- uint8_t flags; /* XEN_NETIF_EXTRA_FLAG_* */
-
- union {
- /*
- * XEN_NETIF_EXTRA_TYPE_GSO:
- */
- struct {
- /*
- * Maximum payload size of each segment. For example, for TCP this
- * is just the path MSS.
- */
- uint16_t size;
-
- /*
- * GSO type. This determines the protocol of the packet and any
- * extra features required to segment the packet properly.
- */
- uint8_t type; /* XEN_NETIF_GSO_TYPE_* */
-
- /* Future expansion. */
- uint8_t pad;
-
- /*
- * GSO features. This specifies any extra GSO features required
- * to process this packet, such as ECN support for TCPv4.
- */
- uint16_t features; /* XEN_NETIF_GSO_FEAT_* */
- } gso;
-
- /*
- * XEN_NETIF_EXTRA_TYPE_MCAST_{ADD,DEL}:
- * Backend advertises availability via 'feature-multicast-control'
- * xenbus node containing value '1'.
- * Frontend requests this feature by advertising
- * 'request-multicast-control' xenbus node containing value '1'.
- * If multicast control is requested then multicast flooding is
- * disabled and the frontend must explicitly register its interest
- * in multicast groups using dummy transmit requests containing
- * MCAST_{ADD,DEL} extra-info fragments.
- */
- struct {
- uint8_t addr[6]; /* Address to add/remove. */
- } mcast;
-
- uint16_t pad[3];
- } u;
-};
-typedef struct netif_extra_info netif_extra_info_t;
-
-struct netif_tx_response {
- uint16_t id;
- int16_t status; /* NETIF_RSP_* */
-};
-typedef struct netif_tx_response netif_tx_response_t;
-
-struct netif_rx_request {
- uint16_t id; /* Echoed in response message. */
- grant_ref_t gref; /* Reference to incoming granted frame */
-};
-typedef struct netif_rx_request netif_rx_request_t;
-
-/* Packet data has been validated against protocol checksum. */
-#define _NETRXF_data_validated (0)
-#define NETRXF_data_validated (1U<<_NETRXF_data_validated)
-
-/* Protocol checksum field is blank in the packet (hardware offload)? */
-#define _NETRXF_csum_blank (1)
-#define NETRXF_csum_blank (1U<<_NETRXF_csum_blank)
-
-/* Packet continues in the next request descriptor. */
-#define _NETRXF_more_data (2)
-#define NETRXF_more_data (1U<<_NETRXF_more_data)
-
-/* Packet to be followed by extra descriptor(s). */
-#define _NETRXF_extra_info (3)
-#define NETRXF_extra_info (1U<<_NETRXF_extra_info)
-
-struct netif_rx_response {
- uint16_t id;
- uint16_t offset; /* Offset in page of start of received packet */
- uint16_t flags; /* NETRXF_* */
- int16_t status; /* -ve: NETIF_RSP_* ; +ve: Rx'ed pkt size. */
-};
-typedef struct netif_rx_response netif_rx_response_t;
-
-/*
- * Generate netif ring structures and types.
- */
-
-DEFINE_RING_TYPES(netif_tx, struct netif_tx_request, struct netif_tx_response);
-DEFINE_RING_TYPES(netif_rx, struct netif_rx_request, struct netif_rx_response);
-
-#define NETIF_RSP_DROPPED -2
-#define NETIF_RSP_ERROR -1
-#define NETIF_RSP_OKAY 0
-/* No response: used for auxiliary requests (e.g., netif_tx_extra). */
-#define NETIF_RSP_NULL 1
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/*
- * PCI Backend/Frontend Common Data Structures & Macros
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
- */
-#ifndef __XEN_PCI_COMMON_H__
-#define __XEN_PCI_COMMON_H__
-
-/* Be sure to bump this number if you change this file */
-#define XEN_PCI_MAGIC "7"
-
-/* xen_pci_sharedinfo flags */
-#define _XEN_PCIF_active (0)
-#define XEN_PCIF_active (1<<_XEN_PCIF_active)
-#define _XEN_PCIB_AERHANDLER (1)
-#define XEN_PCIB_AERHANDLER (1<<_XEN_PCIB_AERHANDLER)
-#define _XEN_PCIB_active (2)
-#define XEN_PCIB_active (1<<_XEN_PCIB_active)
-
-/* xen_pci_op commands */
-#define XEN_PCI_OP_conf_read (0)
-#define XEN_PCI_OP_conf_write (1)
-#define XEN_PCI_OP_enable_msi (2)
-#define XEN_PCI_OP_disable_msi (3)
-#define XEN_PCI_OP_enable_msix (4)
-#define XEN_PCI_OP_disable_msix (5)
-#define XEN_PCI_OP_aer_detected (6)
-#define XEN_PCI_OP_aer_resume (7)
-#define XEN_PCI_OP_aer_mmio (8)
-#define XEN_PCI_OP_aer_slotreset (9)
-#define XEN_PCI_OP_enable_multi_msi (10)
-
-/* xen_pci_op error numbers */
-#define XEN_PCI_ERR_success (0)
-#define XEN_PCI_ERR_dev_not_found (-1)
-#define XEN_PCI_ERR_invalid_offset (-2)
-#define XEN_PCI_ERR_access_denied (-3)
-#define XEN_PCI_ERR_not_implemented (-4)
-/* XEN_PCI_ERR_op_failed - backend failed to complete the operation */
-#define XEN_PCI_ERR_op_failed (-5)
-
-/*
- * it should be PAGE_SIZE-sizeof(struct xen_pci_op))/sizeof(struct msix_entry))
- * Should not exceed 128
- */
-#define SH_INFO_MAX_VEC 128
-
-struct xen_msix_entry {
- uint16_t vector;
- uint16_t entry;
-};
-struct xen_pci_op {
- /* IN: what action to perform: XEN_PCI_OP_* */
- uint32_t cmd;
-
- /* OUT: will contain an error number (if any) from errno.h */
- int32_t err;
-
- /* IN: which device to touch */
- uint32_t domain; /* PCI Domain/Segment */
- uint32_t bus;
- uint32_t devfn;
-
- /* IN: which configuration registers to touch */
- int32_t offset;
- int32_t size;
-
- /* IN/OUT: Contains the result after a READ or the value to WRITE */
- uint32_t value;
- /* IN: Contains extra infor for this operation */
- uint32_t info;
- /*IN: param for msi-x */
- struct xen_msix_entry msix_entries[SH_INFO_MAX_VEC];
-};
-
-/*used for pcie aer handling*/
-struct xen_pcie_aer_op
-{
-
- /* IN: what action to perform: XEN_PCI_OP_* */
- uint32_t cmd;
- /*IN/OUT: return aer_op result or carry error_detected state as input*/
- int32_t err;
-
- /* IN: which device to touch */
- uint32_t domain; /* PCI Domain/Segment*/
- uint32_t bus;
- uint32_t devfn;
-};
-struct xen_pci_sharedinfo {
- /* flags - XEN_PCIF_* */
- uint32_t flags;
- struct xen_pci_op op;
- struct xen_pcie_aer_op aer_op;
-};
-
-#endif /* __XEN_PCI_COMMON_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * protocols.h
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __XEN_PROTOCOLS_H__
-#define __XEN_PROTOCOLS_H__
-
-#define XEN_IO_PROTO_ABI_X86_32 "x86_32-abi"
-#define XEN_IO_PROTO_ABI_X86_64 "x86_64-abi"
-#define XEN_IO_PROTO_ABI_ARM "arm-abi"
-
-#if defined(__i386__)
-# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32
-#elif defined(__x86_64__)
-# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64
-#elif defined(__arm__) || defined(__aarch64__)
-# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_ARM
-#else
-# error arch fixup needed here
-#endif
-
-#endif
+++ /dev/null
-/******************************************************************************
- * ring.h
- *
- * Shared producer-consumer ring macros.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Tim Deegan and Andrew Warfield November 2004.
- */
-
-#ifndef __XEN_PUBLIC_IO_RING_H__
-#define __XEN_PUBLIC_IO_RING_H__
-
-#include "../xen-compat.h"
-
-#if __XEN_INTERFACE_VERSION__ < 0x00030208
-#define xen_mb() mb()
-#define xen_rmb() rmb()
-#define xen_wmb() wmb()
-#endif
-
-typedef unsigned int RING_IDX;
-
-/* Round a 32-bit unsigned constant down to the nearest power of two. */
-#define __RD2(_x) (((_x) & 0x00000002) ? 0x2 : ((_x) & 0x1))
-#define __RD4(_x) (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2 : __RD2(_x))
-#define __RD8(_x) (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4 : __RD4(_x))
-#define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8 : __RD8(_x))
-#define __RD32(_x) (((_x) & 0xffff0000) ? __RD16((_x)>>16)<<16 : __RD16(_x))
-
-/*
- * Calculate size of a shared ring, given the total available space for the
- * ring and indexes (_sz), and the name tag of the request/response structure.
- * A ring contains as many entries as will fit, rounded down to the nearest
- * power of two (so we can mask with (size-1) to loop around).
- */
-#define __CONST_RING_SIZE(_s, _sz) \
- (__RD32(((_sz) - offsetof(struct _s##_sring, ring)) / \
- sizeof(((struct _s##_sring *)0)->ring[0])))
-/*
- * The same for passing in an actual pointer instead of a name tag.
- */
-#define __RING_SIZE(_s, _sz) \
- (__RD32(((_sz) - (long)(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
-
-/*
- * Macros to make the correct C datatypes for a new kind of ring.
- *
- * To make a new ring datatype, you need to have two message structures,
- * let's say request_t, and response_t already defined.
- *
- * In a header where you want the ring datatype declared, you then do:
- *
- * DEFINE_RING_TYPES(mytag, request_t, response_t);
- *
- * These expand out to give you a set of types, as you can see below.
- * The most important of these are:
- *
- * mytag_sring_t - The shared ring.
- * mytag_front_ring_t - The 'front' half of the ring.
- * mytag_back_ring_t - The 'back' half of the ring.
- *
- * To initialize a ring in your code you need to know the location and size
- * of the shared memory area (PAGE_SIZE, for instance). To initialise
- * the front half:
- *
- * mytag_front_ring_t front_ring;
- * SHARED_RING_INIT((mytag_sring_t *)shared_page);
- * FRONT_RING_INIT(&front_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
- *
- * Initializing the back follows similarly (note that only the front
- * initializes the shared ring):
- *
- * mytag_back_ring_t back_ring;
- * BACK_RING_INIT(&back_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
- */
-
-#define DEFINE_RING_TYPES(__name, __req_t, __rsp_t) \
- \
-/* Shared ring entry */ \
-union __name##_sring_entry { \
- __req_t req; \
- __rsp_t rsp; \
-}; \
- \
-/* Shared ring page */ \
-struct __name##_sring { \
- RING_IDX req_prod, req_event; \
- RING_IDX rsp_prod, rsp_event; \
- union { \
- struct { \
- uint8_t smartpoll_active; \
- } netif; \
- struct { \
- uint8_t msg; \
- } tapif_user; \
- uint8_t pvt_pad[4]; \
- } private; \
- uint8_t __pad[44]; \
- union __name##_sring_entry ring[1]; /* variable-length */ \
-}; \
- \
-/* "Front" end's private variables */ \
-struct __name##_front_ring { \
- RING_IDX req_prod_pvt; \
- RING_IDX rsp_cons; \
- unsigned int nr_ents; \
- struct __name##_sring *sring; \
-}; \
- \
-/* "Back" end's private variables */ \
-struct __name##_back_ring { \
- RING_IDX rsp_prod_pvt; \
- RING_IDX req_cons; \
- unsigned int nr_ents; \
- struct __name##_sring *sring; \
-}; \
- \
-/* Syntactic sugar */ \
-typedef struct __name##_sring __name##_sring_t; \
-typedef struct __name##_front_ring __name##_front_ring_t; \
-typedef struct __name##_back_ring __name##_back_ring_t
-
-/*
- * Macros for manipulating rings.
- *
- * FRONT_RING_whatever works on the "front end" of a ring: here
- * requests are pushed on to the ring and responses taken off it.
- *
- * BACK_RING_whatever works on the "back end" of a ring: here
- * requests are taken off the ring and responses put on.
- *
- * N.B. these macros do NO INTERLOCKS OR FLOW CONTROL.
- * This is OK in 1-for-1 request-response situations where the
- * requestor (front end) never has more than RING_SIZE()-1
- * outstanding requests.
- */
-
-/* Initialising empty rings */
-#define SHARED_RING_INIT(_s) do { \
- (_s)->req_prod = (_s)->rsp_prod = 0; \
- (_s)->req_event = (_s)->rsp_event = 1; \
- (void)memset((_s)->private.pvt_pad, 0, sizeof((_s)->private.pvt_pad)); \
- (void)memset((_s)->__pad, 0, sizeof((_s)->__pad)); \
-} while(0)
-
-#define FRONT_RING_INIT(_r, _s, __size) do { \
- (_r)->req_prod_pvt = 0; \
- (_r)->rsp_cons = 0; \
- (_r)->nr_ents = __RING_SIZE(_s, __size); \
- (_r)->sring = (_s); \
-} while (0)
-
-#define BACK_RING_INIT(_r, _s, __size) do { \
- (_r)->rsp_prod_pvt = 0; \
- (_r)->req_cons = 0; \
- (_r)->nr_ents = __RING_SIZE(_s, __size); \
- (_r)->sring = (_s); \
-} while (0)
-
-/* How big is this ring? */
-#define RING_SIZE(_r) \
- ((_r)->nr_ents)
-
-/* Number of free requests (for use on front side only). */
-#define RING_FREE_REQUESTS(_r) \
- (RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons))
-
-/* Test if there is an empty slot available on the front ring.
- * (This is only meaningful from the front. )
- */
-#define RING_FULL(_r) \
- (RING_FREE_REQUESTS(_r) == 0)
-
-/* Test if there are outstanding messages to be processed on a ring. */
-#define RING_HAS_UNCONSUMED_RESPONSES(_r) \
- ((_r)->sring->rsp_prod - (_r)->rsp_cons)
-
-#ifdef __GNUC__
-#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({ \
- unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \
- unsigned int rsp = RING_SIZE(_r) - \
- ((_r)->req_cons - (_r)->rsp_prod_pvt); \
- req < rsp ? req : rsp; \
-})
-#else
-/* Same as above, but without the nice GCC ({ ... }) syntax. */
-#define RING_HAS_UNCONSUMED_REQUESTS(_r) \
- ((((_r)->sring->req_prod - (_r)->req_cons) < \
- (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ? \
- ((_r)->sring->req_prod - (_r)->req_cons) : \
- (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt)))
-#endif
-
-/* Direct access to individual ring elements, by index. */
-#define RING_GET_REQUEST(_r, _idx) \
- (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
-
-#define RING_GET_RESPONSE(_r, _idx) \
- (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
-
-/* Loop termination condition: Would the specified index overflow the ring? */
-#define RING_REQUEST_CONS_OVERFLOW(_r, _cons) \
- (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
-
-/* Ill-behaved frontend determination: Can there be this many requests? */
-#define RING_REQUEST_PROD_OVERFLOW(_r, _prod) \
- (((_prod) - (_r)->rsp_prod_pvt) > RING_SIZE(_r))
-
-#define RING_PUSH_REQUESTS(_r) do { \
- xen_wmb(); /* back sees requests /before/ updated producer index */ \
- (_r)->sring->req_prod = (_r)->req_prod_pvt; \
-} while (0)
-
-#define RING_PUSH_RESPONSES(_r) do { \
- xen_wmb(); /* front sees resps /before/ updated producer index */ \
- (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt; \
-} while (0)
-
-/*
- * Notification hold-off (req_event and rsp_event):
- *
- * When queueing requests or responses on a shared ring, it may not always be
- * necessary to notify the remote end. For example, if requests are in flight
- * in a backend, the front may be able to queue further requests without
- * notifying the back (if the back checks for new requests when it queues
- * responses).
- *
- * When enqueuing requests or responses:
- *
- * Use RING_PUSH_{REQUESTS,RESPONSES}_AND_CHECK_NOTIFY(). The second argument
- * is a boolean return value. True indicates that the receiver requires an
- * asynchronous notification.
- *
- * After dequeuing requests or responses (before sleeping the connection):
- *
- * Use RING_FINAL_CHECK_FOR_REQUESTS() or RING_FINAL_CHECK_FOR_RESPONSES().
- * The second argument is a boolean return value. True indicates that there
- * are pending messages on the ring (i.e., the connection should not be put
- * to sleep).
- *
- * These macros will set the req_event/rsp_event field to trigger a
- * notification on the very next message that is enqueued. If you want to
- * create batches of work (i.e., only receive a notification after several
- * messages have been enqueued) then you will need to create a customised
- * version of the FINAL_CHECK macro in your own code, which sets the event
- * field appropriately.
- */
-
-#define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do { \
- RING_IDX __old = (_r)->sring->req_prod; \
- RING_IDX __new = (_r)->req_prod_pvt; \
- xen_wmb(); /* back sees requests /before/ updated producer index */ \
- (_r)->sring->req_prod = __new; \
- xen_mb(); /* back sees new requests /before/ we check req_event */ \
- (_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) < \
- (RING_IDX)(__new - __old)); \
-} while (0)
-
-#define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do { \
- RING_IDX __old = (_r)->sring->rsp_prod; \
- RING_IDX __new = (_r)->rsp_prod_pvt; \
- xen_wmb(); /* front sees resps /before/ updated producer index */ \
- (_r)->sring->rsp_prod = __new; \
- xen_mb(); /* front sees new resps /before/ we check rsp_event */ \
- (_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) < \
- (RING_IDX)(__new - __old)); \
-} while (0)
-
-#define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do { \
- (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
- if (_work_to_do) break; \
- (_r)->sring->req_event = (_r)->req_cons + 1; \
- xen_mb(); \
- (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
-} while (0)
-
-#define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do { \
- (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
- if (_work_to_do) break; \
- (_r)->sring->rsp_event = (_r)->rsp_cons + 1; \
- xen_mb(); \
- (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
-} while (0)
-
-#endif /* __XEN_PUBLIC_IO_RING_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * tpmif.h
- *
- * TPM I/O interface for Xen guest OSes.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2005, IBM Corporation
- *
- * Author: Stefan Berger, stefanb@us.ibm.com
- * Grant table support: Mahadevan Gomathisankaran
- *
- * This code has been derived from tools/libxc/xen/io/netif.h
- *
- * Copyright (c) 2003-2004, Keir Fraser
- */
-
-#ifndef __XEN_PUBLIC_IO_TPMIF_H__
-#define __XEN_PUBLIC_IO_TPMIF_H__
-
-#include "../grant_table.h"
-
-struct tpmif_tx_request {
- unsigned long addr; /* Machine address of packet. */
- grant_ref_t ref; /* grant table access reference */
- uint16_t unused;
- uint16_t size; /* Packet size in bytes. */
-};
-typedef struct tpmif_tx_request tpmif_tx_request_t;
-
-/*
- * The TPMIF_TX_RING_SIZE defines the number of pages the
- * front-end and backend can exchange (= size of array).
- */
-typedef uint32_t TPMIF_RING_IDX;
-
-#define TPMIF_TX_RING_SIZE 1
-
-/* This structure must fit in a memory page. */
-
-struct tpmif_ring {
- struct tpmif_tx_request req;
-};
-typedef struct tpmif_ring tpmif_ring_t;
-
-struct tpmif_tx_interface {
- struct tpmif_ring ring[TPMIF_TX_RING_SIZE];
-};
-typedef struct tpmif_tx_interface tpmif_tx_interface_t;
-
-/******************************************************************************
- * TPM I/O interface for Xen guest OSes, v2
- *
- * Author: Daniel De Graaf <dgdegra@tycho.nsa.gov>
- *
- * This protocol emulates the request/response behavior of a TPM using a Xen
- * shared memory interface. All interaction with the TPM is at the direction
- * of the frontend, since a TPM (hardware or virtual) is a passive device -
- * the backend only processes commands as requested by the frontend.
- *
- * The frontend sends a request to the TPM by populating the shared page with
- * the request packet, changing the state to TPMIF_STATE_SUBMIT, and sending
- * and event channel notification. When the backend is finished, it will set
- * the state to TPMIF_STATE_FINISH and send an event channel notification.
- *
- * In order to allow long-running commands to be canceled, the frontend can
- * at any time change the state to TPMIF_STATE_CANCEL and send a notification.
- * The TPM can either finish the command (changing state to TPMIF_STATE_FINISH)
- * or can cancel the command and change the state to TPMIF_STATE_IDLE. The TPM
- * can also change the state to TPMIF_STATE_IDLE instead of TPMIF_STATE_FINISH
- * if another reason for cancellation is required - for example, a physical
- * TPM may cancel a command if the interface is seized by another locality.
- *
- * The TPM command format is defined by the TCG, and is available at
- * http://www.trustedcomputinggroup.org/resources/tpm_main_specification
- */
-
-enum tpmif_state {
- TPMIF_STATE_IDLE, /* no contents / vTPM idle / cancel complete */
- TPMIF_STATE_SUBMIT, /* request ready / vTPM working */
- TPMIF_STATE_FINISH, /* response ready / vTPM idle */
- TPMIF_STATE_CANCEL, /* cancel requested / vTPM working */
-};
-/* Note: The backend should only change state to IDLE or FINISH, while the
- * frontend should only change to SUBMIT or CANCEL. Status changes do not need
- * to use atomic operations.
- */
-
-
-/* The shared page for vTPM request/response packets looks like:
- *
- * Offset Contents
- * =================================================
- * 0 struct tpmif_shared_page
- * 16 [optional] List of grant IDs
- * 16+4*nr_extra_pages TPM packet data
- *
- * If the TPM packet data extends beyond the end of a single page, the grant IDs
- * defined in extra_pages are used as if they were mapped immediately following
- * the primary shared page. The grants are allocated by the frontend and mapped
- * by the backend. Before sending a request spanning multiple pages, the
- * frontend should verify that the TPM supports such large requests by querying
- * the TPM_CAP_PROP_INPUT_BUFFER property from the TPM.
- */
-struct tpmif_shared_page {
- uint32_t length; /* request/response length in bytes */
-
- uint8_t state; /* enum tpmif_state */
- uint8_t locality; /* for the current request */
- uint8_t pad; /* should be zero */
-
- uint8_t nr_extra_pages; /* extra pages for long packets; may be zero */
- uint32_t extra_pages[0]; /* grant IDs; length is actually nr_extra_pages */
-};
-typedef struct tpmif_shared_page tpmif_shared_page_t;
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/*
- * usbif.h
- *
- * USB I/O interface for Xen guest OSes.
- *
- * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
- * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __XEN_PUBLIC_IO_USBIF_H__
-#define __XEN_PUBLIC_IO_USBIF_H__
-
-#include "ring.h"
-#include "../grant_table.h"
-
-enum usb_spec_version {
- USB_VER_UNKNOWN = 0,
- USB_VER_USB11,
- USB_VER_USB20,
- USB_VER_USB30, /* not supported yet */
-};
-
-/*
- * USB pipe in usbif_request
- *
- * bits 0-5 are specific bits for virtual USB driver.
- * bits 7-31 are standard urb pipe.
- *
- * - port number(NEW): bits 0-4
- * (USB_MAXCHILDREN is 31)
- *
- * - operation flag(NEW): bit 5
- * (0 = submit urb,
- * 1 = unlink urb)
- *
- * - direction: bit 7
- * (0 = Host-to-Device [Out]
- * 1 = Device-to-Host [In])
- *
- * - device address: bits 8-14
- *
- * - endpoint: bits 15-18
- *
- * - pipe type: bits 30-31
- * (00 = isochronous, 01 = interrupt,
- * 10 = control, 11 = bulk)
- */
-#define usbif_pipeportnum(pipe) ((pipe) & 0x1f)
-#define usbif_setportnum_pipe(pipe, portnum) \
- ((pipe)|(portnum))
-
-#define usbif_pipeunlink(pipe) ((pipe) & 0x20)
-#define usbif_pipesubmit(pipe) (!usbif_pipeunlink(pipe))
-#define usbif_setunlink_pipe(pipe) ((pipe)|(0x20))
-
-#define USBIF_MAX_SEGMENTS_PER_REQUEST (16)
-
-/*
- * RING for transferring urbs.
- */
-struct usbif_request_segment {
- grant_ref_t gref;
- uint16_t offset;
- uint16_t length;
-};
-
-struct usbif_urb_request {
- uint16_t id; /* request id */
- uint16_t nr_buffer_segs; /* number of urb->transfer_buffer segments */
-
- /* basic urb parameter */
- uint32_t pipe;
- uint16_t transfer_flags;
- uint16_t buffer_length;
- union {
- uint8_t ctrl[8]; /* setup_packet (Ctrl) */
-
- struct {
- uint16_t interval; /* maximum (1024*8) in usb core */
- uint16_t start_frame; /* start frame */
- uint16_t number_of_packets; /* number of ISO packet */
- uint16_t nr_frame_desc_segs; /* number of iso_frame_desc segments */
- } isoc;
-
- struct {
- uint16_t interval; /* maximum (1024*8) in usb core */
- uint16_t pad[3];
- } intr;
-
- struct {
- uint16_t unlink_id; /* unlink request id */
- uint16_t pad[3];
- } unlink;
-
- } u;
-
- /* urb data segments */
- struct usbif_request_segment seg[USBIF_MAX_SEGMENTS_PER_REQUEST];
-};
-typedef struct usbif_urb_request usbif_urb_request_t;
-
-struct usbif_urb_response {
- uint16_t id; /* request id */
- uint16_t start_frame; /* start frame (ISO) */
- int32_t status; /* status (non-ISO) */
- int32_t actual_length; /* actual transfer length */
- int32_t error_count; /* number of ISO errors */
-};
-typedef struct usbif_urb_response usbif_urb_response_t;
-
-DEFINE_RING_TYPES(usbif_urb, struct usbif_urb_request, struct usbif_urb_response);
-#define USB_URB_RING_SIZE __CONST_RING_SIZE(usbif_urb, PAGE_SIZE)
-
-/*
- * RING for notifying connect/disconnect events to frontend
- */
-struct usbif_conn_request {
- uint16_t id;
-};
-typedef struct usbif_conn_request usbif_conn_request_t;
-
-struct usbif_conn_response {
- uint16_t id; /* request id */
- uint8_t portnum; /* port number */
- uint8_t speed; /* usb_device_speed */
-};
-typedef struct usbif_conn_response usbif_conn_response_t;
-
-DEFINE_RING_TYPES(usbif_conn, struct usbif_conn_request, struct usbif_conn_response);
-#define USB_CONN_RING_SIZE __CONST_RING_SIZE(usbif_conn, PAGE_SIZE)
-
-#endif /* __XEN_PUBLIC_IO_USBIF_H__ */
+++ /dev/null
-/******************************************************************************
- * vscsiif.h
- *
- * Based on the blkif.h code.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright(c) FUJITSU Limited 2008.
- */
-
-#ifndef __XEN__PUBLIC_IO_SCSI_H__
-#define __XEN__PUBLIC_IO_SCSI_H__
-
-#include "ring.h"
-#include "../grant_table.h"
-
-/*
- * Feature and Parameter Negotiation
- * =================================
- * The two halves of a Xen pvSCSI driver utilize nodes within the XenStore to
- * communicate capabilities and to negotiate operating parameters. This
- * section enumerates these nodes which reside in the respective front and
- * backend portions of the XenStore, following the XenBus convention.
- *
- * Any specified default value is in effect if the corresponding XenBus node
- * is not present in the XenStore.
- *
- * XenStore nodes in sections marked "PRIVATE" are solely for use by the
- * driver side whose XenBus tree contains them.
- *
- *****************************************************************************
- * Backend XenBus Nodes
- *****************************************************************************
- *
- *------------------ Backend Device Identification (PRIVATE) ------------------
- *
- * p-devname
- * Values: string
- *
- * A free string used to identify the physical device (e.g. a disk name).
- *
- * p-dev
- * Values: string
- *
- * A string specifying the backend device: either a 4-tuple "h:c:t:l"
- * (host, controller, target, lun, all integers), or a WWN (e.g.
- * "naa.60014054ac780582").
- *
- * v-dev
- * Values: string
- *
- * A string specifying the frontend device in form of a 4-tuple "h:c:t:l"
- * (host, controller, target, lun, all integers).
- *
- *--------------------------------- Features ---------------------------------
- *
- * feature-sg-grant
- * Values: unsigned [VSCSIIF_SG_TABLESIZE...65535]
- * Default Value: 0
- *
- * Specifies the maximum number of scatter/gather elements in grant pages
- * supported. If not set, the backend supports up to VSCSIIF_SG_TABLESIZE
- * SG elements specified directly in the request.
- *
- *****************************************************************************
- * Frontend XenBus Nodes
- *****************************************************************************
- *
- *----------------------- Request Transport Parameters -----------------------
- *
- * event-channel
- * Values: unsigned
- *
- * The identifier of the Xen event channel used to signal activity
- * in the ring buffer.
- *
- * ring-ref
- * Values: unsigned
- *
- * The Xen grant reference granting permission for the backend to map
- * the sole page in a single page sized ring buffer.
- *
- * protocol
- * Values: string (XEN_IO_PROTO_ABI_*)
- * Default Value: XEN_IO_PROTO_ABI_NATIVE
- *
- * The machine ABI rules governing the format of all ring request and
- * response structures.
- */
-
-/* Requests from the frontend to the backend */
-
-/*
- * Request a SCSI operation specified via a CDB in vscsiif_request.cmnd.
- * The target is specified via channel, id and lun.
- *
- * The operation to be performed is specified via a CDB in cmnd[], the length
- * of the CDB is in cmd_len. sc_data_direction specifies the direction of data
- * (to the device, from the device, or none at all).
- *
- * If data is to be transferred to or from the device the buffer(s) in the
- * guest memory is/are specified via one or multiple scsiif_request_segment
- * descriptors each specifying a memory page via a grant_ref_t, a offset into
- * the page and the length of the area in that page. All scsiif_request_segment
- * areas concatenated form the resulting data buffer used by the operation.
- * If the number of scsiif_request_segment areas is not too large (less than
- * or equal VSCSIIF_SG_TABLESIZE) the areas can be specified directly in the
- * seg[] array and the number of valid scsiif_request_segment elements is to be
- * set in nr_segments.
- *
- * If "feature-sg-grant" in the Xenstore is set it is possible to specify more
- * than VSCSIIF_SG_TABLESIZE scsiif_request_segment elements via indirection.
- * The maximum number of allowed scsiif_request_segment elements is the value
- * of the "feature-sg-grant" entry from Xenstore. When using indirection the
- * seg[] array doesn't contain specifications of the data buffers, but
- * references to scsiif_request_segment arrays, which in turn reference the
- * data buffers. While nr_segments holds the number of populated seg[] entries
- * (plus the set VSCSIIF_SG_GRANT bit), the number of scsiif_request_segment
- * elements referencing the target data buffers is calculated from the lengths
- * of the seg[] elements (the sum of all valid seg[].length divided by the
- * size of one scsiif_request_segment structure). The frontend may use a mix of
- * direct and indirect requests.
- */
-#define VSCSIIF_ACT_SCSI_CDB 1
-
-/*
- * Request abort of a running operation for the specified target given by
- * channel, id, lun and the operation's rqid in ref_rqid.
- */
-#define VSCSIIF_ACT_SCSI_ABORT 2
-
-/*
- * Request a device reset of the specified target (channel and id).
- */
-#define VSCSIIF_ACT_SCSI_RESET 3
-
-/*
- * Preset scatter/gather elements for a following request. Deprecated.
- * Keeping the define only to avoid usage of the value "4" for other actions.
- */
-#define VSCSIIF_ACT_SCSI_SG_PRESET 4
-
-/*
- * Maximum scatter/gather segments per request.
- *
- * Considering balance between allocating at least 16 "vscsiif_request"
- * structures on one page (4096 bytes) and the number of scatter/gather
- * elements needed, we decided to use 26 as a magic number.
- *
- * If "feature-sg-grant" is set, more scatter/gather elements can be specified
- * by placing them in one or more (up to VSCSIIF_SG_TABLESIZE) granted pages.
- * In this case the vscsiif_request seg elements don't contain references to
- * the user data, but to the SG elements referencing the user data.
- */
-#define VSCSIIF_SG_TABLESIZE 26
-
-/*
- * based on Linux kernel 2.6.18, still valid
- *
- * Changing these values requires support of multiple protocols via the rings
- * as "old clients" will blindly use these values and the resulting structure
- * sizes.
- */
-#define VSCSIIF_MAX_COMMAND_SIZE 16
-#define VSCSIIF_SENSE_BUFFERSIZE 96
-
-struct scsiif_request_segment {
- grant_ref_t gref;
- uint16_t offset;
- uint16_t length;
-};
-typedef struct scsiif_request_segment vscsiif_segment_t;
-
-#define VSCSIIF_SG_PER_PAGE (PAGE_SIZE / sizeof(struct scsiif_request_segment))
-
-/* Size of one request is 252 bytes */
-struct vscsiif_request {
- uint16_t rqid; /* private guest value, echoed in resp */
- uint8_t act; /* command between backend and frontend */
- uint8_t cmd_len; /* valid CDB bytes */
-
- uint8_t cmnd[VSCSIIF_MAX_COMMAND_SIZE]; /* the CDB */
- uint16_t timeout_per_command; /* deprecated: timeout in secs, 0=default */
- uint16_t channel, id, lun; /* (virtual) device specification */
- uint16_t ref_rqid; /* command abort reference */
- uint8_t sc_data_direction; /* for DMA_TO_DEVICE(1)
- DMA_FROM_DEVICE(2)
- DMA_NONE(3) requests */
- uint8_t nr_segments; /* Number of pieces of scatter-gather */
-/*
- * flag in nr_segments: SG elements via grant page
- *
- * If VSCSIIF_SG_GRANT is set, the low 7 bits of nr_segments specify the number
- * of grant pages containing SG elements. Usable if "feature-sg-grant" set.
- */
-#define VSCSIIF_SG_GRANT 0x80
-
- vscsiif_segment_t seg[VSCSIIF_SG_TABLESIZE];
- uint32_t reserved[3];
-};
-typedef struct vscsiif_request vscsiif_request_t;
-
-/*
- * The following interface is deprecated!
- */
-#define VSCSIIF_SG_LIST_SIZE ((sizeof(vscsiif_request_t) - 4) \
- / sizeof(vscsiif_segment_t))
-
-struct vscsiif_sg_list {
- /* First two fields must match struct vscsiif_request! */
- uint16_t rqid; /* private guest value, must match main req */
- uint8_t act; /* VSCSIIF_ACT_SCSI_SG_PRESET */
- uint8_t nr_segments; /* Number of pieces of scatter-gather */
- vscsiif_segment_t seg[VSCSIIF_SG_LIST_SIZE];
-};
-typedef struct vscsiif_sg_list vscsiif_sg_list_t;
-/* End of deprecated interface */
-
-/* Size of one response is 252 bytes */
-struct vscsiif_response {
- uint16_t rqid; /* identifies request */
- uint8_t act; /* deprecated: valid only if SG_PRESET supported */
- uint8_t sense_len;
- uint8_t sense_buffer[VSCSIIF_SENSE_BUFFERSIZE];
- int32_t rslt;
- uint32_t residual_len; /* request bufflen -
- return the value from physical device */
- uint32_t reserved[36];
-};
-typedef struct vscsiif_response vscsiif_response_t;
-
-DEFINE_RING_TYPES(vscsiif, struct vscsiif_request, struct vscsiif_response);
-
-
-#endif /*__XEN__PUBLIC_IO_SCSI_H__*/
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/*****************************************************************************
- * xenbus.h
- *
- * Xenbus protocol details.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (C) 2005 XenSource Ltd.
- */
-
-#ifndef _XEN_PUBLIC_IO_XENBUS_H
-#define _XEN_PUBLIC_IO_XENBUS_H
-
-/*
- * The state of either end of the Xenbus, i.e. the current communication
- * status of initialisation across the bus. States here imply nothing about
- * the state of the connection between the driver and the kernel's device
- * layers.
- */
-enum xenbus_state {
- XenbusStateUnknown = 0,
-
- XenbusStateInitialising = 1,
-
- /*
- * InitWait: Finished early initialisation but waiting for information
- * from the peer or hotplug scripts.
- */
- XenbusStateInitWait = 2,
-
- /*
- * Initialised: Waiting for a connection from the peer.
- */
- XenbusStateInitialised = 3,
-
- XenbusStateConnected = 4,
-
- /*
- * Closing: The device is being closed due to an error or an unplug event.
- */
- XenbusStateClosing = 5,
-
- XenbusStateClosed = 6,
-
- /*
- * Reconfiguring: The device is being reconfigured.
- */
- XenbusStateReconfiguring = 7,
-
- XenbusStateReconfigured = 8
-};
-typedef enum xenbus_state XenbusState;
-
-#endif /* _XEN_PUBLIC_IO_XENBUS_H */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/*
- * Details of the "wire" protocol between Xen Store Daemon and client
- * library or guest kernel.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (C) 2005 Rusty Russell IBM Corporation
- */
-
-#ifndef _XS_WIRE_H
-#define _XS_WIRE_H
-
-enum xsd_sockmsg_type
-{
- XS_DEBUG,
- XS_DIRECTORY,
- XS_READ,
- XS_GET_PERMS,
- XS_WATCH,
- XS_UNWATCH,
- XS_TRANSACTION_START,
- XS_TRANSACTION_END,
- XS_INTRODUCE,
- XS_RELEASE,
- XS_GET_DOMAIN_PATH,
- XS_WRITE,
- XS_MKDIR,
- XS_RM,
- XS_SET_PERMS,
- XS_WATCH_EVENT,
- XS_ERROR,
- XS_IS_DOMAIN_INTRODUCED,
- XS_RESUME,
- XS_SET_TARGET,
- XS_RESTRICT,
- XS_RESET_WATCHES,
-
- XS_INVALID = 0xffff /* Guaranteed to remain an invalid type */
-};
-
-#define XS_WRITE_NONE "NONE"
-#define XS_WRITE_CREATE "CREATE"
-#define XS_WRITE_CREATE_EXCL "CREATE|EXCL"
-
-/* We hand errors as strings, for portability. */
-struct xsd_errors
-{
- int errnum;
- const char *errstring;
-};
-#ifdef EINVAL
-#define XSD_ERROR(x) { x, #x }
-/* LINTED: static unused */
-static struct xsd_errors xsd_errors[]
-#if defined(__GNUC__)
-__attribute__((unused))
-#endif
- = {
- XSD_ERROR(EINVAL),
- XSD_ERROR(EACCES),
- XSD_ERROR(EEXIST),
- XSD_ERROR(EISDIR),
- XSD_ERROR(ENOENT),
- XSD_ERROR(ENOMEM),
- XSD_ERROR(ENOSPC),
- XSD_ERROR(EIO),
- XSD_ERROR(ENOTEMPTY),
- XSD_ERROR(ENOSYS),
- XSD_ERROR(EROFS),
- XSD_ERROR(EBUSY),
- XSD_ERROR(EAGAIN),
- XSD_ERROR(EISCONN),
- XSD_ERROR(E2BIG)
-};
-#endif
-
-struct xsd_sockmsg
-{
- uint32_t type; /* XS_??? */
- uint32_t req_id;/* Request identifier, echoed in daemon's response. */
- uint32_t tx_id; /* Transaction id (0 if not related to a transaction). */
- uint32_t len; /* Length of data following this. */
-
- /* Generally followed by nul-terminated string(s). */
-};
-
-enum xs_watch_type
-{
- XS_WATCH_PATH = 0,
- XS_WATCH_TOKEN
-};
-
-/*
- * `incontents 150 xenstore_struct XenStore wire protocol.
- *
- * Inter-domain shared memory communications. */
-#define XENSTORE_RING_SIZE 1024
-typedef uint32_t XENSTORE_RING_IDX;
-#define MASK_XENSTORE_IDX(idx) ((idx) & (XENSTORE_RING_SIZE-1))
-struct xenstore_domain_interface {
- char req[XENSTORE_RING_SIZE]; /* Requests to xenstore daemon. */
- char rsp[XENSTORE_RING_SIZE]; /* Replies and async watch events. */
- XENSTORE_RING_IDX req_cons, req_prod;
- XENSTORE_RING_IDX rsp_cons, rsp_prod;
- uint32_t server_features; /* Bitmap of features supported by the server */
- uint32_t connection;
-};
-
-/* Violating this is very bad. See docs/misc/xenstore.txt. */
-#define XENSTORE_PAYLOAD_MAX 4096
-
-/* Violating these just gets you an error back */
-#define XENSTORE_ABS_PATH_MAX 3072
-#define XENSTORE_REL_PATH_MAX 2048
-
-/* The ability to reconnect a ring */
-#define XENSTORE_SERVER_FEATURE_RECONNECTION 1
-
-/* Valid values for the connection field */
-#define XENSTORE_CONNECTED 0 /* the steady-state */
-#define XENSTORE_RECONNECT 1 /* guest has initiated a reconnect */
-
-#endif /* _XS_WIRE_H */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * kexec.h - Public portion
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Xen port written by:
- * - Simon 'Horms' Horman <horms@verge.net.au>
- * - Magnus Damm <magnus@valinux.co.jp>
- */
-
-#ifndef _XEN_PUBLIC_KEXEC_H
-#define _XEN_PUBLIC_KEXEC_H
-
-
-/* This file describes the Kexec / Kdump hypercall interface for Xen.
- *
- * Kexec under vanilla Linux allows a user to reboot the physical machine
- * into a new user-specified kernel. The Xen port extends this idea
- * to allow rebooting of the machine from dom0. When kexec for dom0
- * is used to reboot, both the hypervisor and the domains get replaced
- * with some other kernel. It is possible to kexec between vanilla
- * Linux and Xen and back again. Xen to Xen works well too.
- *
- * The hypercall interface for kexec can be divided into three main
- * types of hypercall operations:
- *
- * 1) Range information:
- * This is used by the dom0 kernel to ask the hypervisor about various
- * address information. This information is needed to allow kexec-tools
- * to fill in the ELF headers for /proc/vmcore properly.
- *
- * 2) Load and unload of images:
- * There are no big surprises here, the kexec binary from kexec-tools
- * runs in userspace in dom0. The tool loads/unloads data into the
- * dom0 kernel such as new kernel, initramfs and hypervisor. When
- * loaded the dom0 kernel performs a load hypercall operation, and
- * before releasing all page references the dom0 kernel calls unload.
- *
- * 3) Kexec operation:
- * This is used to start a previously loaded kernel.
- */
-
-#include "xen.h"
-
-#if defined(__i386__) || defined(__x86_64__)
-#define KEXEC_XEN_NO_PAGES 17
-#endif
-
-/*
- * Prototype for this hypercall is:
- * int kexec_op(int cmd, void *args)
- * @cmd == KEXEC_CMD_...
- * KEXEC operation to perform
- * @args == Operation-specific extra arguments (NULL if none).
- */
-
-/*
- * Kexec supports two types of operation:
- * - kexec into a regular kernel, very similar to a standard reboot
- * - KEXEC_TYPE_DEFAULT is used to specify this type
- * - kexec into a special "crash kernel", aka kexec-on-panic
- * - KEXEC_TYPE_CRASH is used to specify this type
- * - parts of our system may be broken at kexec-on-panic time
- * - the code should be kept as simple and self-contained as possible
- */
-
-#define KEXEC_TYPE_DEFAULT 0
-#define KEXEC_TYPE_CRASH 1
-
-
-/* The kexec implementation for Xen allows the user to load two
- * types of kernels, KEXEC_TYPE_DEFAULT and KEXEC_TYPE_CRASH.
- * All data needed for a kexec reboot is kept in one xen_kexec_image_t
- * per "instance". The data mainly consists of machine address lists to pages
- * together with destination addresses. The data in xen_kexec_image_t
- * is passed to the "code page" which is one page of code that performs
- * the final relocations before jumping to the new kernel.
- */
-
-typedef struct xen_kexec_image {
-#if defined(__i386__) || defined(__x86_64__)
- unsigned long page_list[KEXEC_XEN_NO_PAGES];
-#endif
- unsigned long indirection_page;
- unsigned long start_address;
-} xen_kexec_image_t;
-
-/*
- * Perform kexec having previously loaded a kexec or kdump kernel
- * as appropriate.
- * type == KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH [in]
- *
- * Control is transferred to the image entry point with the host in
- * the following state.
- *
- * - The image may be executed on any PCPU and all other PCPUs are
- * stopped.
- *
- * - Local interrupts are disabled.
- *
- * - Register values are undefined.
- *
- * - The image segments have writeable 1:1 virtual to machine
- * mappings. The location of any page tables is undefined and these
- * page table frames are not be mapped.
- */
-#define KEXEC_CMD_kexec 0
-typedef struct xen_kexec_exec {
- int type;
-} xen_kexec_exec_t;
-
-/*
- * Load/Unload kernel image for kexec or kdump.
- * type == KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH [in]
- * image == relocation information for kexec (ignored for unload) [in]
- */
-#define KEXEC_CMD_kexec_load_v1 1 /* obsolete since 0x00040400 */
-#define KEXEC_CMD_kexec_unload_v1 2 /* obsolete since 0x00040400 */
-typedef struct xen_kexec_load_v1 {
- int type;
- xen_kexec_image_t image;
-} xen_kexec_load_v1_t;
-
-#define KEXEC_RANGE_MA_CRASH 0 /* machine address and size of crash area */
-#define KEXEC_RANGE_MA_XEN 1 /* machine address and size of Xen itself */
-#define KEXEC_RANGE_MA_CPU 2 /* machine address and size of a CPU note */
-#define KEXEC_RANGE_MA_XENHEAP 3 /* machine address and size of xenheap
- * Note that although this is adjacent
- * to Xen it exists in a separate EFI
- * region on ia64, and thus needs to be
- * inserted into iomem_machine separately */
-#define KEXEC_RANGE_MA_BOOT_PARAM 4 /* Obsolete: machine address and size of
- * the ia64_boot_param */
-#define KEXEC_RANGE_MA_EFI_MEMMAP 5 /* machine address and size of
- * of the EFI Memory Map */
-#define KEXEC_RANGE_MA_VMCOREINFO 6 /* machine address and size of vmcoreinfo */
-
-/*
- * Find the address and size of certain memory areas
- * range == KEXEC_RANGE_... [in]
- * nr == physical CPU number (starting from 0) if KEXEC_RANGE_MA_CPU [in]
- * size == number of bytes reserved in window [out]
- * start == address of the first byte in the window [out]
- */
-#define KEXEC_CMD_kexec_get_range 3
-typedef struct xen_kexec_range {
- int range;
- int nr;
- unsigned long size;
- unsigned long start;
-} xen_kexec_range_t;
-
-#if __XEN_INTERFACE_VERSION__ >= 0x00040400
-/*
- * A contiguous chunk of a kexec image and it's destination machine
- * address.
- */
-typedef struct xen_kexec_segment {
- union {
- XEN_GUEST_HANDLE(const_void) h;
- uint64_t _pad;
- } buf;
- uint64_t buf_size;
- uint64_t dest_maddr;
- uint64_t dest_size;
-} xen_kexec_segment_t;
-DEFINE_XEN_GUEST_HANDLE(xen_kexec_segment_t);
-
-/*
- * Load a kexec image into memory.
- *
- * For KEXEC_TYPE_DEFAULT images, the segments may be anywhere in RAM.
- * The image is relocated prior to being executed.
- *
- * For KEXEC_TYPE_CRASH images, each segment of the image must reside
- * in the memory region reserved for kexec (KEXEC_RANGE_MA_CRASH) and
- * the entry point must be within the image. The caller is responsible
- * for ensuring that multiple images do not overlap.
- *
- * All image segments will be loaded to their destination machine
- * addresses prior to being executed. The trailing portion of any
- * segments with a source buffer (from dest_maddr + buf_size to
- * dest_maddr + dest_size) will be zeroed.
- *
- * Segments with no source buffer will be accessible to the image when
- * it is executed.
- */
-
-#define KEXEC_CMD_kexec_load 4
-typedef struct xen_kexec_load {
- uint8_t type; /* One of KEXEC_TYPE_* */
- uint8_t _pad;
- uint16_t arch; /* ELF machine type (EM_*). */
- uint32_t nr_segments;
- union {
- XEN_GUEST_HANDLE(xen_kexec_segment_t) h;
- uint64_t _pad;
- } segments;
- uint64_t entry_maddr; /* image entry point machine address. */
-} xen_kexec_load_t;
-DEFINE_XEN_GUEST_HANDLE(xen_kexec_load_t);
-
-/*
- * Unload a kexec image.
- *
- * Type must be one of KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH.
- */
-#define KEXEC_CMD_kexec_unload 5
-typedef struct xen_kexec_unload {
- uint8_t type;
-} xen_kexec_unload_t;
-DEFINE_XEN_GUEST_HANDLE(xen_kexec_unload_t);
-
-#else /* __XEN_INTERFACE_VERSION__ < 0x00040400 */
-
-#define KEXEC_CMD_kexec_load KEXEC_CMD_kexec_load_v1
-#define KEXEC_CMD_kexec_unload KEXEC_CMD_kexec_unload_v1
-#define xen_kexec_load xen_kexec_load_v1
-#define xen_kexec_load_t xen_kexec_load_v1_t
-
-#endif
-
-#endif /* _XEN_PUBLIC_KEXEC_H */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * mem_event.h
- *
- * Memory event common structures.
- *
- * Copyright (c) 2009 by Citrix Systems, Inc. (Patrick Colp)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _XEN_PUBLIC_MEM_EVENT_H
-#define _XEN_PUBLIC_MEM_EVENT_H
-
-#include "xen.h"
-#include "io/ring.h"
-
-/* Memory event flags */
-#define MEM_EVENT_FLAG_VCPU_PAUSED (1 << 0)
-#define MEM_EVENT_FLAG_DROP_PAGE (1 << 1)
-#define MEM_EVENT_FLAG_EVICT_FAIL (1 << 2)
-#define MEM_EVENT_FLAG_FOREIGN (1 << 3)
-#define MEM_EVENT_FLAG_DUMMY (1 << 4)
-/*
- * Emulate the fault-causing instruction (if set in the event response flags).
- * This will allow the guest to continue execution without lifting the page
- * access restrictions.
- */
-#define MEM_EVENT_FLAG_EMULATE (1 << 5)
-/*
- * Same as MEM_EVENT_FLAG_EMULATE, but with write operations or operations
- * potentially having side effects (like memory mapped or port I/O) disabled.
- */
-#define MEM_EVENT_FLAG_EMULATE_NOWRITE (1 << 6)
-
-/* Reasons for the memory event request */
-#define MEM_EVENT_REASON_UNKNOWN 0 /* typical reason */
-#define MEM_EVENT_REASON_VIOLATION 1 /* access violation, GFN is address */
-#define MEM_EVENT_REASON_CR0 2 /* CR0 was hit: gfn is new CR0 value, gla is previous */
-#define MEM_EVENT_REASON_CR3 3 /* CR3 was hit: gfn is new CR3 value, gla is previous */
-#define MEM_EVENT_REASON_CR4 4 /* CR4 was hit: gfn is new CR4 value, gla is previous */
-#define MEM_EVENT_REASON_INT3 5 /* int3 was hit: gla/gfn are RIP */
-#define MEM_EVENT_REASON_SINGLESTEP 6 /* single step was invoked: gla/gfn are RIP */
-#define MEM_EVENT_REASON_MSR 7 /* MSR was hit: gfn is MSR value, gla is MSR address;
- does NOT honour HVMPME_onchangeonly */
-
-/* Using a custom struct (not hvm_hw_cpu) so as to not fill
- * the mem_event ring buffer too quickly. */
-struct mem_event_regs_x86 {
- uint64_t rax;
- uint64_t rcx;
- uint64_t rdx;
- uint64_t rbx;
- uint64_t rsp;
- uint64_t rbp;
- uint64_t rsi;
- uint64_t rdi;
- uint64_t r8;
- uint64_t r9;
- uint64_t r10;
- uint64_t r11;
- uint64_t r12;
- uint64_t r13;
- uint64_t r14;
- uint64_t r15;
- uint64_t rflags;
- uint64_t dr7;
- uint64_t rip;
- uint64_t cr0;
- uint64_t cr2;
- uint64_t cr3;
- uint64_t cr4;
- uint64_t sysenter_cs;
- uint64_t sysenter_esp;
- uint64_t sysenter_eip;
- uint64_t msr_efer;
- uint64_t msr_star;
- uint64_t msr_lstar;
- uint64_t fs_base;
- uint64_t gs_base;
- uint32_t cs_arbytes;
- uint32_t _pad;
-};
-
-typedef struct mem_event_st {
- uint32_t flags;
- uint32_t vcpu_id;
-
- uint64_t gfn;
- uint64_t offset;
- uint64_t gla; /* if gla_valid */
-
- uint32_t p2mt;
-
- uint16_t access_r:1;
- uint16_t access_w:1;
- uint16_t access_x:1;
- uint16_t gla_valid:1;
- uint16_t fault_with_gla:1;
- uint16_t fault_in_gpt:1;
- uint16_t available:10;
-
- uint16_t reason;
- struct mem_event_regs_x86 x86_regs;
-} mem_event_request_t, mem_event_response_t;
-
-DEFINE_RING_TYPES(mem_event, mem_event_request_t, mem_event_response_t);
-
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * memory.h
- *
- * Memory reservation and information.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
- */
-
-#ifndef __XEN_PUBLIC_MEMORY_H__
-#define __XEN_PUBLIC_MEMORY_H__
-
-#include "xen.h"
-
-/*
- * Increase or decrease the specified domain's memory reservation. Returns the
- * number of extents successfully allocated or freed.
- * arg == addr of struct xen_memory_reservation.
- */
-#define XENMEM_increase_reservation 0
-#define XENMEM_decrease_reservation 1
-#define XENMEM_populate_physmap 6
-
-#if __XEN_INTERFACE_VERSION__ >= 0x00030209
-/*
- * Maximum # bits addressable by the user of the allocated region (e.g., I/O
- * devices often have a 32-bit limitation even in 64-bit systems). If zero
- * then the user has no addressing restriction. This field is not used by
- * XENMEM_decrease_reservation.
- */
-#define XENMEMF_address_bits(x) (x)
-#define XENMEMF_get_address_bits(x) ((x) & 0xffu)
-/* NUMA node to allocate from. */
-#define XENMEMF_node(x) (((x) + 1) << 8)
-#define XENMEMF_get_node(x) ((((x) >> 8) - 1) & 0xffu)
-/* Flag to populate physmap with populate-on-demand entries */
-#define XENMEMF_populate_on_demand (1<<16)
-/* Flag to request allocation only from the node specified */
-#define XENMEMF_exact_node_request (1<<17)
-#define XENMEMF_exact_node(n) (XENMEMF_node(n) | XENMEMF_exact_node_request)
-#endif
-
-struct xen_memory_reservation {
-
- /*
- * XENMEM_increase_reservation:
- * OUT: MFN (*not* GMFN) bases of extents that were allocated
- * XENMEM_decrease_reservation:
- * IN: GMFN bases of extents to free
- * XENMEM_populate_physmap:
- * IN: GPFN bases of extents to populate with memory
- * OUT: GMFN bases of extents that were allocated
- * (NB. This command also updates the mach_to_phys translation table)
- * XENMEM_claim_pages:
- * IN: must be zero
- */
- XEN_GUEST_HANDLE(xen_pfn_t) extent_start;
-
- /* Number of extents, and size/alignment of each (2^extent_order pages). */
- xen_ulong_t nr_extents;
- unsigned int extent_order;
-
-#if __XEN_INTERFACE_VERSION__ >= 0x00030209
- /* XENMEMF flags. */
- unsigned int mem_flags;
-#else
- unsigned int address_bits;
-#endif
-
- /*
- * Domain whose reservation is being changed.
- * Unprivileged domains can specify only DOMID_SELF.
- */
- domid_t domid;
-};
-typedef struct xen_memory_reservation xen_memory_reservation_t;
-DEFINE_XEN_GUEST_HANDLE(xen_memory_reservation_t);
-
-/*
- * An atomic exchange of memory pages. If return code is zero then
- * @out.extent_list provides GMFNs of the newly-allocated memory.
- * Returns zero on complete success, otherwise a negative error code.
- * On complete success then always @nr_exchanged == @in.nr_extents.
- * On partial success @nr_exchanged indicates how much work was done.
- */
-#define XENMEM_exchange 11
-struct xen_memory_exchange {
- /*
- * [IN] Details of memory extents to be exchanged (GMFN bases).
- * Note that @in.address_bits is ignored and unused.
- */
- struct xen_memory_reservation in;
-
- /*
- * [IN/OUT] Details of new memory extents.
- * We require that:
- * 1. @in.domid == @out.domid
- * 2. @in.nr_extents << @in.extent_order ==
- * @out.nr_extents << @out.extent_order
- * 3. @in.extent_start and @out.extent_start lists must not overlap
- * 4. @out.extent_start lists GPFN bases to be populated
- * 5. @out.extent_start is overwritten with allocated GMFN bases
- */
- struct xen_memory_reservation out;
-
- /*
- * [OUT] Number of input extents that were successfully exchanged:
- * 1. The first @nr_exchanged input extents were successfully
- * deallocated.
- * 2. The corresponding first entries in the output extent list correctly
- * indicate the GMFNs that were successfully exchanged.
- * 3. All other input and output extents are untouched.
- * 4. If not all input exents are exchanged then the return code of this
- * command will be non-zero.
- * 5. THIS FIELD MUST BE INITIALISED TO ZERO BY THE CALLER!
- */
- xen_ulong_t nr_exchanged;
-};
-typedef struct xen_memory_exchange xen_memory_exchange_t;
-DEFINE_XEN_GUEST_HANDLE(xen_memory_exchange_t);
-
-/*
- * Returns the maximum machine frame number of mapped RAM in this system.
- * This command always succeeds (it never returns an error code).
- * arg == NULL.
- */
-#define XENMEM_maximum_ram_page 2
-
-/*
- * Returns the current or maximum memory reservation, in pages, of the
- * specified domain (may be DOMID_SELF). Returns -ve errcode on failure.
- * arg == addr of domid_t.
- */
-#define XENMEM_current_reservation 3
-#define XENMEM_maximum_reservation 4
-
-/*
- * Returns the maximum GPFN in use by the guest, or -ve errcode on failure.
- */
-#define XENMEM_maximum_gpfn 14
-
-/*
- * Returns a list of MFN bases of 2MB extents comprising the machine_to_phys
- * mapping table. Architectures which do not have a m2p table do not implement
- * this command.
- * arg == addr of xen_machphys_mfn_list_t.
- */
-#define XENMEM_machphys_mfn_list 5
-struct xen_machphys_mfn_list {
- /*
- * Size of the 'extent_start' array. Fewer entries will be filled if the
- * machphys table is smaller than max_extents * 2MB.
- */
- unsigned int max_extents;
-
- /*
- * Pointer to buffer to fill with list of extent starts. If there are
- * any large discontiguities in the machine address space, 2MB gaps in
- * the machphys table will be represented by an MFN base of zero.
- */
- XEN_GUEST_HANDLE(xen_pfn_t) extent_start;
-
- /*
- * Number of extents written to the above array. This will be smaller
- * than 'max_extents' if the machphys table is smaller than max_e * 2MB.
- */
- unsigned int nr_extents;
-};
-typedef struct xen_machphys_mfn_list xen_machphys_mfn_list_t;
-DEFINE_XEN_GUEST_HANDLE(xen_machphys_mfn_list_t);
-
-/*
- * For a compat caller, this is identical to XENMEM_machphys_mfn_list.
- *
- * For a non compat caller, this functions similarly to
- * XENMEM_machphys_mfn_list, but returns the mfns making up the compatibility
- * m2p table.
- */
-#define XENMEM_machphys_compat_mfn_list 25
-
-/*
- * Returns the location in virtual address space of the machine_to_phys
- * mapping table. Architectures which do not have a m2p table, or which do not
- * map it by default into guest address space, do not implement this command.
- * arg == addr of xen_machphys_mapping_t.
- */
-#define XENMEM_machphys_mapping 12
-struct xen_machphys_mapping {
- xen_ulong_t v_start, v_end; /* Start and end virtual addresses. */
- xen_ulong_t max_mfn; /* Maximum MFN that can be looked up. */
-};
-typedef struct xen_machphys_mapping xen_machphys_mapping_t;
-DEFINE_XEN_GUEST_HANDLE(xen_machphys_mapping_t);
-
-/* Source mapping space. */
-/* ` enum phys_map_space { */
-#define XENMAPSPACE_shared_info 0 /* shared info page */
-#define XENMAPSPACE_grant_table 1 /* grant table page */
-#define XENMAPSPACE_gmfn 2 /* GMFN */
-#define XENMAPSPACE_gmfn_range 3 /* GMFN range, XENMEM_add_to_physmap only. */
-#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another dom,
- * XENMEM_add_to_physmap_batch only. */
-/* ` } */
-
-/*
- * Sets the GPFN at which a particular page appears in the specified guest's
- * pseudophysical address space.
- * arg == addr of xen_add_to_physmap_t.
- */
-#define XENMEM_add_to_physmap 7
-struct xen_add_to_physmap {
- /* Which domain to change the mapping for. */
- domid_t domid;
-
- /* Number of pages to go through for gmfn_range */
- uint16_t size;
-
- unsigned int space; /* => enum phys_map_space */
-
-#define XENMAPIDX_grant_table_status 0x80000000
-
- /* Index into space being mapped. */
- xen_ulong_t idx;
-
- /* GPFN in domid where the source mapping page should appear. */
- xen_pfn_t gpfn;
-};
-typedef struct xen_add_to_physmap xen_add_to_physmap_t;
-DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
-
-/* A batched version of add_to_physmap. */
-#define XENMEM_add_to_physmap_batch 23
-struct xen_add_to_physmap_batch {
- /* IN */
- /* Which domain to change the mapping for. */
- domid_t domid;
- uint16_t space; /* => enum phys_map_space */
-
- /* Number of pages to go through */
- uint16_t size;
- domid_t foreign_domid; /* IFF gmfn_foreign */
-
- /* Indexes into space being mapped. */
- XEN_GUEST_HANDLE(xen_ulong_t) idxs;
-
- /* GPFN in domid where the source mapping page should appear. */
- XEN_GUEST_HANDLE(xen_pfn_t) gpfns;
-
- /* OUT */
-
- /* Per index error code. */
- XEN_GUEST_HANDLE(int) errs;
-};
-typedef struct xen_add_to_physmap_batch xen_add_to_physmap_batch_t;
-DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_batch_t);
-
-#if __XEN_INTERFACE_VERSION__ < 0x00040400
-#define XENMEM_add_to_physmap_range XENMEM_add_to_physmap_batch
-#define xen_add_to_physmap_range xen_add_to_physmap_batch
-typedef struct xen_add_to_physmap_batch xen_add_to_physmap_range_t;
-DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_range_t);
-#endif
-
-/*
- * Unmaps the page appearing at a particular GPFN from the specified guest's
- * pseudophysical address space.
- * arg == addr of xen_remove_from_physmap_t.
- */
-#define XENMEM_remove_from_physmap 15
-struct xen_remove_from_physmap {
- /* Which domain to change the mapping for. */
- domid_t domid;
-
- /* GPFN of the current mapping of the page. */
- xen_pfn_t gpfn;
-};
-typedef struct xen_remove_from_physmap xen_remove_from_physmap_t;
-DEFINE_XEN_GUEST_HANDLE(xen_remove_from_physmap_t);
-
-/*** REMOVED ***/
-/*#define XENMEM_translate_gpfn_list 8*/
-
-/*
- * Returns the pseudo-physical memory map as it was when the domain
- * was started (specified by XENMEM_set_memory_map).
- * arg == addr of xen_memory_map_t.
- */
-#define XENMEM_memory_map 9
-struct xen_memory_map {
- /*
- * On call the number of entries which can be stored in buffer. On
- * return the number of entries which have been stored in
- * buffer.
- */
- unsigned int nr_entries;
-
- /*
- * Entries in the buffer are in the same format as returned by the
- * BIOS INT 0x15 EAX=0xE820 call.
- */
- XEN_GUEST_HANDLE(void) buffer;
-};
-typedef struct xen_memory_map xen_memory_map_t;
-DEFINE_XEN_GUEST_HANDLE(xen_memory_map_t);
-
-/*
- * Returns the real physical memory map. Passes the same structure as
- * XENMEM_memory_map.
- * arg == addr of xen_memory_map_t.
- */
-#define XENMEM_machine_memory_map 10
-
-/*
- * Set the pseudo-physical memory map of a domain, as returned by
- * XENMEM_memory_map.
- * arg == addr of xen_foreign_memory_map_t.
- */
-#define XENMEM_set_memory_map 13
-struct xen_foreign_memory_map {
- domid_t domid;
- struct xen_memory_map map;
-};
-typedef struct xen_foreign_memory_map xen_foreign_memory_map_t;
-DEFINE_XEN_GUEST_HANDLE(xen_foreign_memory_map_t);
-
-#define XENMEM_set_pod_target 16
-#define XENMEM_get_pod_target 17
-struct xen_pod_target {
- /* IN */
- uint64_t target_pages;
- /* OUT */
- uint64_t tot_pages;
- uint64_t pod_cache_pages;
- uint64_t pod_entries;
- /* IN */
- domid_t domid;
-};
-typedef struct xen_pod_target xen_pod_target_t;
-
-#if defined(__XEN__) || defined(__XEN_TOOLS__)
-
-#ifndef uint64_aligned_t
-#define uint64_aligned_t uint64_t
-#endif
-
-/*
- * Get the number of MFNs saved through memory sharing.
- * The call never fails.
- */
-#define XENMEM_get_sharing_freed_pages 18
-#define XENMEM_get_sharing_shared_pages 19
-
-#define XENMEM_paging_op 20
-#define XENMEM_paging_op_nominate 0
-#define XENMEM_paging_op_evict 1
-#define XENMEM_paging_op_prep 2
-
-struct xen_mem_event_op {
- uint8_t op; /* XENMEM_*_op_* */
- domid_t domain;
-
-
- /* PAGING_PREP IN: buffer to immediately fill page in */
- uint64_aligned_t buffer;
- /* Other OPs */
- uint64_aligned_t gfn; /* IN: gfn of page being operated on */
-};
-typedef struct xen_mem_event_op xen_mem_event_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_mem_event_op_t);
-
-#define XENMEM_access_op 21
-#define XENMEM_access_op_resume 0
-#define XENMEM_access_op_set_access 1
-#define XENMEM_access_op_get_access 2
-
-typedef enum {
- XENMEM_access_n,
- XENMEM_access_r,
- XENMEM_access_w,
- XENMEM_access_rw,
- XENMEM_access_x,
- XENMEM_access_rx,
- XENMEM_access_wx,
- XENMEM_access_rwx,
- /*
- * Page starts off as r-x, but automatically
- * change to r-w on a write
- */
- XENMEM_access_rx2rw,
- /*
- * Log access: starts off as n, automatically
- * goes to rwx, generating an event without
- * pausing the vcpu
- */
- XENMEM_access_n2rwx,
- /* Take the domain default */
- XENMEM_access_default
-} xenmem_access_t;
-
-struct xen_mem_access_op {
- /* XENMEM_access_op_* */
- uint8_t op;
- /* xenmem_access_t */
- uint8_t access;
- domid_t domid;
- /*
- * Number of pages for set op
- * Ignored on setting default access and other ops
- */
- uint32_t nr;
- /*
- * First pfn for set op
- * pfn for get op
- * ~0ull is used to set and get the default access for pages
- */
- uint64_aligned_t pfn;
-};
-typedef struct xen_mem_access_op xen_mem_access_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_mem_access_op_t);
-
-#define XENMEM_sharing_op 22
-#define XENMEM_sharing_op_nominate_gfn 0
-#define XENMEM_sharing_op_nominate_gref 1
-#define XENMEM_sharing_op_share 2
-#define XENMEM_sharing_op_resume 3
-#define XENMEM_sharing_op_debug_gfn 4
-#define XENMEM_sharing_op_debug_mfn 5
-#define XENMEM_sharing_op_debug_gref 6
-#define XENMEM_sharing_op_add_physmap 7
-#define XENMEM_sharing_op_audit 8
-
-#define XENMEM_SHARING_OP_S_HANDLE_INVALID (-10)
-#define XENMEM_SHARING_OP_C_HANDLE_INVALID (-9)
-
-/* The following allows sharing of grant refs. This is useful
- * for sharing utilities sitting as "filters" in IO backends
- * (e.g. memshr + blktap(2)). The IO backend is only exposed
- * to grant references, and this allows sharing of the grefs */
-#define XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG (1ULL << 62)
-
-#define XENMEM_SHARING_OP_FIELD_MAKE_GREF(field, val) \
- (field) = (XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG | val)
-#define XENMEM_SHARING_OP_FIELD_IS_GREF(field) \
- ((field) & XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG)
-#define XENMEM_SHARING_OP_FIELD_GET_GREF(field) \
- ((field) & (~XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG))
-
-struct xen_mem_sharing_op {
- uint8_t op; /* XENMEM_sharing_op_* */
- domid_t domain;
-
- union {
- struct mem_sharing_op_nominate { /* OP_NOMINATE_xxx */
- union {
- uint64_aligned_t gfn; /* IN: gfn to nominate */
- uint32_t grant_ref; /* IN: grant ref to nominate */
- } u;
- uint64_aligned_t handle; /* OUT: the handle */
- } nominate;
- struct mem_sharing_op_share { /* OP_SHARE/ADD_PHYSMAP */
- uint64_aligned_t source_gfn; /* IN: the gfn of the source page */
- uint64_aligned_t source_handle; /* IN: handle to the source page */
- uint64_aligned_t client_gfn; /* IN: the client gfn */
- uint64_aligned_t client_handle; /* IN: handle to the client page */
- domid_t client_domain; /* IN: the client domain id */
- } share;
- struct mem_sharing_op_debug { /* OP_DEBUG_xxx */
- union {
- uint64_aligned_t gfn; /* IN: gfn to debug */
- uint64_aligned_t mfn; /* IN: mfn to debug */
- uint32_t gref; /* IN: gref to debug */
- } u;
- } debug;
- } u;
-};
-typedef struct xen_mem_sharing_op xen_mem_sharing_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_mem_sharing_op_t);
-
-/*
- * Attempt to stake a claim for a domain on a quantity of pages
- * of system RAM, but _not_ assign specific pageframes. Only
- * arithmetic is performed so the hypercall is very fast and need
- * not be preemptible, thus sidestepping time-of-check-time-of-use
- * races for memory allocation. Returns 0 if the hypervisor page
- * allocator has atomically and successfully claimed the requested
- * number of pages, else non-zero.
- *
- * Any domain may have only one active claim. When sufficient memory
- * has been allocated to resolve the claim, the claim silently expires.
- * Claiming zero pages effectively resets any outstanding claim and
- * is always successful.
- *
- * Note that a valid claim may be staked even after memory has been
- * allocated for a domain. In this case, the claim is not incremental,
- * i.e. if the domain's tot_pages is 3, and a claim is staked for 10,
- * only 7 additional pages are claimed.
- *
- * Caller must be privileged or the hypercall fails.
- */
-#define XENMEM_claim_pages 24
-
-/*
- * XENMEM_claim_pages flags - the are no flags at this time.
- * The zero value is appropiate.
- */
-
-#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
-
-/*
- * XENMEM_get_vnumainfo used by guest to get
- * vNUMA topology from hypervisor.
- */
-#define XENMEM_get_vnumainfo 26
-
-/* vNUMA node memory ranges */
-struct xen_vmemrange {
- uint64_t start, end;
- unsigned int flags;
- unsigned int nid;
-};
-typedef struct xen_vmemrange xen_vmemrange_t;
-DEFINE_XEN_GUEST_HANDLE(xen_vmemrange_t);
-
-/*
- * vNUMA topology specifies vNUMA node number, distance table,
- * memory ranges and vcpu mapping provided for guests.
- * XENMEM_get_vnumainfo hypercall expects to see from guest
- * nr_vnodes, nr_vmemranges and nr_vcpus to indicate available memory.
- * After filling guests structures, nr_vnodes, nr_vmemranges and nr_vcpus
- * copied back to guest. Domain returns expected values of nr_vnodes,
- * nr_vmemranges and nr_vcpus to guest if the values where incorrect.
- */
-struct xen_vnuma_topology_info {
- /* IN */
- domid_t domid;
- uint16_t pad;
- /* IN/OUT */
- unsigned int nr_vnodes;
- unsigned int nr_vcpus;
- unsigned int nr_vmemranges;
- /* OUT */
- union {
- XEN_GUEST_HANDLE(uint) h;
- uint64_t pad;
- } vdistance;
- union {
- XEN_GUEST_HANDLE(uint) h;
- uint64_t pad;
- } vcpu_to_vnode;
- union {
- XEN_GUEST_HANDLE(xen_vmemrange_t) h;
- uint64_t pad;
- } vmemrange;
-};
-typedef struct xen_vnuma_topology_info xen_vnuma_topology_info_t;
-DEFINE_XEN_GUEST_HANDLE(xen_vnuma_topology_info_t);
-
-/* Next available subop number is 27 */
-
-#endif /* __XEN_PUBLIC_MEMORY_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * nmi.h
- *
- * NMI callback registration and reason codes.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
- */
-
-#ifndef __XEN_PUBLIC_NMI_H__
-#define __XEN_PUBLIC_NMI_H__
-
-#include "xen.h"
-
-/*
- * NMI reason codes:
- * Currently these are x86-specific, stored in arch_shared_info.nmi_reason.
- */
- /* I/O-check error reported via ISA port 0x61, bit 6. */
-#define _XEN_NMIREASON_io_error 0
-#define XEN_NMIREASON_io_error (1UL << _XEN_NMIREASON_io_error)
- /* PCI SERR reported via ISA port 0x61, bit 7. */
-#define _XEN_NMIREASON_pci_serr 1
-#define XEN_NMIREASON_pci_serr (1UL << _XEN_NMIREASON_pci_serr)
-#if __XEN_INTERFACE_VERSION__ < 0x00040300 /* legacy alias of the above */
- /* Parity error reported via ISA port 0x61, bit 7. */
-#define _XEN_NMIREASON_parity_error 1
-#define XEN_NMIREASON_parity_error (1UL << _XEN_NMIREASON_parity_error)
-#endif
- /* Unknown hardware-generated NMI. */
-#define _XEN_NMIREASON_unknown 2
-#define XEN_NMIREASON_unknown (1UL << _XEN_NMIREASON_unknown)
-
-/*
- * long nmi_op(unsigned int cmd, void *arg)
- * NB. All ops return zero on success, else a negative error code.
- */
-
-/*
- * Register NMI callback for this (calling) VCPU. Currently this only makes
- * sense for domain 0, vcpu 0. All other callers will be returned EINVAL.
- * arg == pointer to xennmi_callback structure.
- */
-#define XENNMI_register_callback 0
-struct xennmi_callback {
- unsigned long handler_address;
- unsigned long pad;
-};
-typedef struct xennmi_callback xennmi_callback_t;
-DEFINE_XEN_GUEST_HANDLE(xennmi_callback_t);
-
-/*
- * Deregister NMI callback for this (calling) VCPU.
- * arg == NULL.
- */
-#define XENNMI_unregister_callback 1
-
-#endif /* __XEN_PUBLIC_NMI_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __XEN_PUBLIC_PHYSDEV_H__
-#define __XEN_PUBLIC_PHYSDEV_H__
-
-#include "xen.h"
-
-/*
- * Prototype for this hypercall is:
- * int physdev_op(int cmd, void *args)
- * @cmd == PHYSDEVOP_??? (physdev operation).
- * @args == Operation-specific extra arguments (NULL if none).
- */
-
-/*
- * Notify end-of-interrupt (EOI) for the specified IRQ.
- * @arg == pointer to physdev_eoi structure.
- */
-#define PHYSDEVOP_eoi 12
-struct physdev_eoi {
- /* IN */
- uint32_t irq;
-};
-typedef struct physdev_eoi physdev_eoi_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_eoi_t);
-
-/*
- * Register a shared page for the hypervisor to indicate whether the guest
- * must issue PHYSDEVOP_eoi. The semantics of PHYSDEVOP_eoi change slightly
- * once the guest used this function in that the associated event channel
- * will automatically get unmasked. The page registered is used as a bit
- * array indexed by Xen's PIRQ value.
- */
-#define PHYSDEVOP_pirq_eoi_gmfn_v1 17
-/*
- * Register a shared page for the hypervisor to indicate whether the
- * guest must issue PHYSDEVOP_eoi. This hypercall is very similar to
- * PHYSDEVOP_pirq_eoi_gmfn_v1 but it doesn't change the semantics of
- * PHYSDEVOP_eoi. The page registered is used as a bit array indexed by
- * Xen's PIRQ value.
- */
-#define PHYSDEVOP_pirq_eoi_gmfn_v2 28
-struct physdev_pirq_eoi_gmfn {
- /* IN */
- xen_pfn_t gmfn;
-};
-typedef struct physdev_pirq_eoi_gmfn physdev_pirq_eoi_gmfn_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_pirq_eoi_gmfn_t);
-
-/*
- * Query the status of an IRQ line.
- * @arg == pointer to physdev_irq_status_query structure.
- */
-#define PHYSDEVOP_irq_status_query 5
-struct physdev_irq_status_query {
- /* IN */
- uint32_t irq;
- /* OUT */
- uint32_t flags; /* XENIRQSTAT_* */
-};
-typedef struct physdev_irq_status_query physdev_irq_status_query_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_irq_status_query_t);
-
-/* Need to call PHYSDEVOP_eoi when the IRQ has been serviced? */
-#define _XENIRQSTAT_needs_eoi (0)
-#define XENIRQSTAT_needs_eoi (1U<<_XENIRQSTAT_needs_eoi)
-
-/* IRQ shared by multiple guests? */
-#define _XENIRQSTAT_shared (1)
-#define XENIRQSTAT_shared (1U<<_XENIRQSTAT_shared)
-
-/*
- * Set the current VCPU's I/O privilege level.
- * @arg == pointer to physdev_set_iopl structure.
- */
-#define PHYSDEVOP_set_iopl 6
-struct physdev_set_iopl {
- /* IN */
- uint32_t iopl;
-};
-typedef struct physdev_set_iopl physdev_set_iopl_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_set_iopl_t);
-
-/*
- * Set the current VCPU's I/O-port permissions bitmap.
- * @arg == pointer to physdev_set_iobitmap structure.
- */
-#define PHYSDEVOP_set_iobitmap 7
-struct physdev_set_iobitmap {
- /* IN */
-#if __XEN_INTERFACE_VERSION__ >= 0x00030205
- XEN_GUEST_HANDLE(uint8) bitmap;
-#else
- uint8_t *bitmap;
-#endif
- uint32_t nr_ports;
-};
-typedef struct physdev_set_iobitmap physdev_set_iobitmap_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_set_iobitmap_t);
-
-/*
- * Read or write an IO-APIC register.
- * @arg == pointer to physdev_apic structure.
- */
-#define PHYSDEVOP_apic_read 8
-#define PHYSDEVOP_apic_write 9
-struct physdev_apic {
- /* IN */
- unsigned long apic_physbase;
- uint32_t reg;
- /* IN or OUT */
- uint32_t value;
-};
-typedef struct physdev_apic physdev_apic_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_apic_t);
-
-/*
- * Allocate or free a physical upcall vector for the specified IRQ line.
- * @arg == pointer to physdev_irq structure.
- */
-#define PHYSDEVOP_alloc_irq_vector 10
-#define PHYSDEVOP_free_irq_vector 11
-struct physdev_irq {
- /* IN */
- uint32_t irq;
- /* IN or OUT */
- uint32_t vector;
-};
-typedef struct physdev_irq physdev_irq_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_irq_t);
-
-#define MAP_PIRQ_TYPE_MSI 0x0
-#define MAP_PIRQ_TYPE_GSI 0x1
-#define MAP_PIRQ_TYPE_UNKNOWN 0x2
-#define MAP_PIRQ_TYPE_MSI_SEG 0x3
-#define MAP_PIRQ_TYPE_MULTI_MSI 0x4
-
-#define PHYSDEVOP_map_pirq 13
-struct physdev_map_pirq {
- domid_t domid;
- /* IN */
- int type;
- /* IN (ignored for ..._MULTI_MSI) */
- int index;
- /* IN or OUT */
- int pirq;
- /* IN - high 16 bits hold segment for ..._MSI_SEG and ..._MULTI_MSI */
- int bus;
- /* IN */
- int devfn;
- /* IN (also OUT for ..._MULTI_MSI) */
- int entry_nr;
- /* IN */
- uint64_t table_base;
-};
-typedef struct physdev_map_pirq physdev_map_pirq_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_map_pirq_t);
-
-#define PHYSDEVOP_unmap_pirq 14
-struct physdev_unmap_pirq {
- domid_t domid;
- /* IN */
- int pirq;
-};
-
-typedef struct physdev_unmap_pirq physdev_unmap_pirq_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_unmap_pirq_t);
-
-#define PHYSDEVOP_manage_pci_add 15
-#define PHYSDEVOP_manage_pci_remove 16
-struct physdev_manage_pci {
- /* IN */
- uint8_t bus;
- uint8_t devfn;
-};
-
-typedef struct physdev_manage_pci physdev_manage_pci_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_t);
-
-#define PHYSDEVOP_restore_msi 19
-struct physdev_restore_msi {
- /* IN */
- uint8_t bus;
- uint8_t devfn;
-};
-typedef struct physdev_restore_msi physdev_restore_msi_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_restore_msi_t);
-
-#define PHYSDEVOP_manage_pci_add_ext 20
-struct physdev_manage_pci_ext {
- /* IN */
- uint8_t bus;
- uint8_t devfn;
- unsigned is_extfn;
- unsigned is_virtfn;
- struct {
- uint8_t bus;
- uint8_t devfn;
- } physfn;
-};
-
-typedef struct physdev_manage_pci_ext physdev_manage_pci_ext_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_ext_t);
-
-/*
- * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op()
- * hypercall since 0x00030202.
- */
-struct physdev_op {
- uint32_t cmd;
- union {
- struct physdev_irq_status_query irq_status_query;
- struct physdev_set_iopl set_iopl;
- struct physdev_set_iobitmap set_iobitmap;
- struct physdev_apic apic_op;
- struct physdev_irq irq_op;
- } u;
-};
-typedef struct physdev_op physdev_op_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_op_t);
-
-#define PHYSDEVOP_setup_gsi 21
-struct physdev_setup_gsi {
- int gsi;
- /* IN */
- uint8_t triggering;
- /* IN */
- uint8_t polarity;
- /* IN */
-};
-
-typedef struct physdev_setup_gsi physdev_setup_gsi_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_setup_gsi_t);
-
-/* leave PHYSDEVOP 22 free */
-
-/* type is MAP_PIRQ_TYPE_GSI or MAP_PIRQ_TYPE_MSI
- * the hypercall returns a free pirq */
-#define PHYSDEVOP_get_free_pirq 23
-struct physdev_get_free_pirq {
- /* IN */
- int type;
- /* OUT */
- uint32_t pirq;
-};
-
-typedef struct physdev_get_free_pirq physdev_get_free_pirq_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_get_free_pirq_t);
-
-#define XEN_PCI_MMCFG_RESERVED 0x1
-
-#define PHYSDEVOP_pci_mmcfg_reserved 24
-struct physdev_pci_mmcfg_reserved {
- uint64_t address;
- uint16_t segment;
- uint8_t start_bus;
- uint8_t end_bus;
- uint32_t flags;
-};
-typedef struct physdev_pci_mmcfg_reserved physdev_pci_mmcfg_reserved_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_pci_mmcfg_reserved_t);
-
-#define XEN_PCI_DEV_EXTFN 0x1
-#define XEN_PCI_DEV_VIRTFN 0x2
-#define XEN_PCI_DEV_PXM 0x4
-
-#define PHYSDEVOP_pci_device_add 25
-struct physdev_pci_device_add {
- /* IN */
- uint16_t seg;
- uint8_t bus;
- uint8_t devfn;
- uint32_t flags;
- struct {
- uint8_t bus;
- uint8_t devfn;
- } physfn;
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
- uint32_t optarr[];
-#elif defined(__GNUC__)
- uint32_t optarr[0];
-#endif
-};
-typedef struct physdev_pci_device_add physdev_pci_device_add_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_pci_device_add_t);
-
-#define PHYSDEVOP_pci_device_remove 26
-#define PHYSDEVOP_restore_msi_ext 27
-/*
- * Dom0 should use these two to announce MMIO resources assigned to
- * MSI-X capable devices won't (prepare) or may (release) change.
- */
-#define PHYSDEVOP_prepare_msix 30
-#define PHYSDEVOP_release_msix 31
-struct physdev_pci_device {
- /* IN */
- uint16_t seg;
- uint8_t bus;
- uint8_t devfn;
-};
-typedef struct physdev_pci_device physdev_pci_device_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_pci_device_t);
-
-#define PHYSDEVOP_DBGP_RESET_PREPARE 1
-#define PHYSDEVOP_DBGP_RESET_DONE 2
-
-#define PHYSDEVOP_DBGP_BUS_UNKNOWN 0
-#define PHYSDEVOP_DBGP_BUS_PCI 1
-
-#define PHYSDEVOP_dbgp_op 29
-struct physdev_dbgp_op {
- /* IN */
- uint8_t op;
- uint8_t bus;
- union {
- struct physdev_pci_device pci;
- } u;
-};
-typedef struct physdev_dbgp_op physdev_dbgp_op_t;
-DEFINE_XEN_GUEST_HANDLE(physdev_dbgp_op_t);
-
-/*
- * Notify that some PIRQ-bound event channels have been unmasked.
- * ** This command is obsolete since interface version 0x00030202 and is **
- * ** unsupported by newer versions of Xen. **
- */
-#define PHYSDEVOP_IRQ_UNMASK_NOTIFY 4
-
-#if __XEN_INTERFACE_VERSION__ < 0x00040600
-/*
- * These all-capitals physdev operation names are superceded by the new names
- * (defined above) since interface version 0x00030202. The guard above was
- * added post-4.5 only though and hence shouldn't check for 0x00030202.
- */
-#define PHYSDEVOP_IRQ_STATUS_QUERY PHYSDEVOP_irq_status_query
-#define PHYSDEVOP_SET_IOPL PHYSDEVOP_set_iopl
-#define PHYSDEVOP_SET_IOBITMAP PHYSDEVOP_set_iobitmap
-#define PHYSDEVOP_APIC_READ PHYSDEVOP_apic_read
-#define PHYSDEVOP_APIC_WRITE PHYSDEVOP_apic_write
-#define PHYSDEVOP_ASSIGN_VECTOR PHYSDEVOP_alloc_irq_vector
-#define PHYSDEVOP_FREE_VECTOR PHYSDEVOP_free_irq_vector
-#define PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY XENIRQSTAT_needs_eoi
-#define PHYSDEVOP_IRQ_SHARED XENIRQSTAT_shared
-#endif
-
-#if __XEN_INTERFACE_VERSION__ < 0x00040200
-#define PHYSDEVOP_pirq_eoi_gmfn PHYSDEVOP_pirq_eoi_gmfn_v1
-#else
-#define PHYSDEVOP_pirq_eoi_gmfn PHYSDEVOP_pirq_eoi_gmfn_v2
-#endif
-
-#endif /* __XEN_PUBLIC_PHYSDEV_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * platform.h
- *
- * Hardware platform operations. Intended for use by domain-0 kernel.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2002-2006, K Fraser
- */
-
-#ifndef __XEN_PUBLIC_PLATFORM_H__
-#define __XEN_PUBLIC_PLATFORM_H__
-
-#include "xen.h"
-
-#define XENPF_INTERFACE_VERSION 0x03000001
-
-/*
- * Set clock such that it would read <secs,nsecs> after 00:00:00 UTC,
- * 1 January, 1970 if the current system time was <system_time>.
- */
-#define XENPF_settime 17
-struct xenpf_settime {
- /* IN variables. */
- uint32_t secs;
- uint32_t nsecs;
- uint64_t system_time;
-};
-typedef struct xenpf_settime xenpf_settime_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_settime_t);
-
-/*
- * Request memory range (@mfn, @mfn+@nr_mfns-1) to have type @type.
- * On x86, @type is an architecture-defined MTRR memory type.
- * On success, returns the MTRR that was used (@reg) and a handle that can
- * be passed to XENPF_DEL_MEMTYPE to accurately tear down the new setting.
- * (x86-specific).
- */
-#define XENPF_add_memtype 31
-struct xenpf_add_memtype {
- /* IN variables. */
- xen_pfn_t mfn;
- uint64_t nr_mfns;
- uint32_t type;
- /* OUT variables. */
- uint32_t handle;
- uint32_t reg;
-};
-typedef struct xenpf_add_memtype xenpf_add_memtype_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_add_memtype_t);
-
-/*
- * Tear down an existing memory-range type. If @handle is remembered then it
- * should be passed in to accurately tear down the correct setting (in case
- * of overlapping memory regions with differing types). If it is not known
- * then @handle should be set to zero. In all cases @reg must be set.
- * (x86-specific).
- */
-#define XENPF_del_memtype 32
-struct xenpf_del_memtype {
- /* IN variables. */
- uint32_t handle;
- uint32_t reg;
-};
-typedef struct xenpf_del_memtype xenpf_del_memtype_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_del_memtype_t);
-
-/* Read current type of an MTRR (x86-specific). */
-#define XENPF_read_memtype 33
-struct xenpf_read_memtype {
- /* IN variables. */
- uint32_t reg;
- /* OUT variables. */
- xen_pfn_t mfn;
- uint64_t nr_mfns;
- uint32_t type;
-};
-typedef struct xenpf_read_memtype xenpf_read_memtype_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_read_memtype_t);
-
-#define XENPF_microcode_update 35
-struct xenpf_microcode_update {
- /* IN variables. */
- XEN_GUEST_HANDLE(const_void) data;/* Pointer to microcode data */
- uint32_t length; /* Length of microcode data. */
-};
-typedef struct xenpf_microcode_update xenpf_microcode_update_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_microcode_update_t);
-
-#define XENPF_platform_quirk 39
-#define QUIRK_NOIRQBALANCING 1 /* Do not restrict IO-APIC RTE targets */
-#define QUIRK_IOAPIC_BAD_REGSEL 2 /* IO-APIC REGSEL forgets its value */
-#define QUIRK_IOAPIC_GOOD_REGSEL 3 /* IO-APIC REGSEL behaves properly */
-struct xenpf_platform_quirk {
- /* IN variables. */
- uint32_t quirk_id;
-};
-typedef struct xenpf_platform_quirk xenpf_platform_quirk_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_platform_quirk_t);
-
-#define XENPF_efi_runtime_call 49
-#define XEN_EFI_get_time 1
-#define XEN_EFI_set_time 2
-#define XEN_EFI_get_wakeup_time 3
-#define XEN_EFI_set_wakeup_time 4
-#define XEN_EFI_get_next_high_monotonic_count 5
-#define XEN_EFI_get_variable 6
-#define XEN_EFI_set_variable 7
-#define XEN_EFI_get_next_variable_name 8
-#define XEN_EFI_query_variable_info 9
-#define XEN_EFI_query_capsule_capabilities 10
-#define XEN_EFI_update_capsule 11
-struct xenpf_efi_runtime_call {
- uint32_t function;
- /*
- * This field is generally used for per sub-function flags (defined
- * below), except for the XEN_EFI_get_next_high_monotonic_count case,
- * where it holds the single returned value.
- */
- uint32_t misc;
- xen_ulong_t status;
- union {
-#define XEN_EFI_GET_TIME_SET_CLEARS_NS 0x00000001
- struct {
- struct xenpf_efi_time {
- uint16_t year;
- uint8_t month;
- uint8_t day;
- uint8_t hour;
- uint8_t min;
- uint8_t sec;
- uint32_t ns;
- int16_t tz;
- uint8_t daylight;
- } time;
- uint32_t resolution;
- uint32_t accuracy;
- } get_time;
-
- struct xenpf_efi_time set_time;
-
-#define XEN_EFI_GET_WAKEUP_TIME_ENABLED 0x00000001
-#define XEN_EFI_GET_WAKEUP_TIME_PENDING 0x00000002
- struct xenpf_efi_time get_wakeup_time;
-
-#define XEN_EFI_SET_WAKEUP_TIME_ENABLE 0x00000001
-#define XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY 0x00000002
- struct xenpf_efi_time set_wakeup_time;
-
-#define XEN_EFI_VARIABLE_NON_VOLATILE 0x00000001
-#define XEN_EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
-#define XEN_EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
- struct {
- XEN_GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
- xen_ulong_t size;
- XEN_GUEST_HANDLE(void) data;
- struct xenpf_efi_guid {
- uint32_t data1;
- uint16_t data2;
- uint16_t data3;
- uint8_t data4[8];
- } vendor_guid;
- } get_variable, set_variable;
-
- struct {
- xen_ulong_t size;
- XEN_GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
- struct xenpf_efi_guid vendor_guid;
- } get_next_variable_name;
-
-#define XEN_EFI_VARINFO_BOOT_SNAPSHOT 0x00000001
- struct {
- uint32_t attr;
- uint64_t max_store_size;
- uint64_t remain_store_size;
- uint64_t max_size;
- } query_variable_info;
-
- struct {
- XEN_GUEST_HANDLE(void) capsule_header_array;
- xen_ulong_t capsule_count;
- uint64_t max_capsule_size;
- uint32_t reset_type;
- } query_capsule_capabilities;
-
- struct {
- XEN_GUEST_HANDLE(void) capsule_header_array;
- xen_ulong_t capsule_count;
- uint64_t sg_list; /* machine address */
- } update_capsule;
- } u;
-};
-typedef struct xenpf_efi_runtime_call xenpf_efi_runtime_call_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_efi_runtime_call_t);
-
-#define XENPF_firmware_info 50
-#define XEN_FW_DISK_INFO 1 /* from int 13 AH=08/41/48 */
-#define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */
-#define XEN_FW_VBEDDC_INFO 3 /* from int 10 AX=4f15 */
-#define XEN_FW_EFI_INFO 4 /* from EFI */
-#define XEN_FW_EFI_VERSION 0
-#define XEN_FW_EFI_CONFIG_TABLE 1
-#define XEN_FW_EFI_VENDOR 2
-#define XEN_FW_EFI_MEM_INFO 3
-#define XEN_FW_EFI_RT_VERSION 4
-#define XEN_FW_EFI_PCI_ROM 5
-#define XEN_FW_KBD_SHIFT_FLAGS 5
-struct xenpf_firmware_info {
- /* IN variables. */
- uint32_t type;
- uint32_t index;
- /* OUT variables. */
- union {
- struct {
- /* Int13, Fn48: Check Extensions Present. */
- uint8_t device; /* %dl: bios device number */
- uint8_t version; /* %ah: major version */
- uint16_t interface_support; /* %cx: support bitmap */
- /* Int13, Fn08: Legacy Get Device Parameters. */
- uint16_t legacy_max_cylinder; /* %cl[7:6]:%ch: max cyl # */
- uint8_t legacy_max_head; /* %dh: max head # */
- uint8_t legacy_sectors_per_track; /* %cl[5:0]: max sector # */
- /* Int13, Fn41: Get Device Parameters (as filled into %ds:%esi). */
- /* NB. First uint16_t of buffer must be set to buffer size. */
- XEN_GUEST_HANDLE(void) edd_params;
- } disk_info; /* XEN_FW_DISK_INFO */
- struct {
- uint8_t device; /* bios device number */
- uint32_t mbr_signature; /* offset 0x1b8 in mbr */
- } disk_mbr_signature; /* XEN_FW_DISK_MBR_SIGNATURE */
- struct {
- /* Int10, AX=4F15: Get EDID info. */
- uint8_t capabilities;
- uint8_t edid_transfer_time;
- /* must refer to 128-byte buffer */
- XEN_GUEST_HANDLE(uint8) edid;
- } vbeddc_info; /* XEN_FW_VBEDDC_INFO */
- union xenpf_efi_info {
- uint32_t version;
- struct {
- uint64_t addr; /* EFI_CONFIGURATION_TABLE */
- uint32_t nent;
- } cfg;
- struct {
- uint32_t revision;
- uint32_t bufsz; /* input, in bytes */
- XEN_GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
- } vendor;
- struct {
- uint64_t addr;
- uint64_t size;
- uint64_t attr;
- uint32_t type;
- } mem;
- struct {
- /* IN variables */
- uint16_t segment;
- uint8_t bus;
- uint8_t devfn;
- uint16_t vendor;
- uint16_t devid;
- /* OUT variables */
- uint64_t address;
- xen_ulong_t size;
- } pci_rom;
- } efi_info; /* XEN_FW_EFI_INFO */
-
- /* Int16, Fn02: Get keyboard shift flags. */
- uint8_t kbd_shift_flags; /* XEN_FW_KBD_SHIFT_FLAGS */
- } u;
-};
-typedef struct xenpf_firmware_info xenpf_firmware_info_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_firmware_info_t);
-
-#define XENPF_enter_acpi_sleep 51
-struct xenpf_enter_acpi_sleep {
- /* IN variables */
-#if __XEN_INTERFACE_VERSION__ < 0x00040300
- uint16_t pm1a_cnt_val; /* PM1a control value. */
- uint16_t pm1b_cnt_val; /* PM1b control value. */
-#else
- uint16_t val_a; /* PM1a control / sleep type A. */
- uint16_t val_b; /* PM1b control / sleep type B. */
-#endif
- uint32_t sleep_state; /* Which state to enter (Sn). */
-#define XENPF_ACPI_SLEEP_EXTENDED 0x00000001
- uint32_t flags; /* XENPF_ACPI_SLEEP_*. */
-};
-typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t);
-
-#define XENPF_change_freq 52
-struct xenpf_change_freq {
- /* IN variables */
- uint32_t flags; /* Must be zero. */
- uint32_t cpu; /* Physical cpu. */
- uint64_t freq; /* New frequency (Hz). */
-};
-typedef struct xenpf_change_freq xenpf_change_freq_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_change_freq_t);
-
-/*
- * Get idle times (nanoseconds since boot) for physical CPUs specified in the
- * @cpumap_bitmap with range [0..@cpumap_nr_cpus-1]. The @idletime array is
- * indexed by CPU number; only entries with the corresponding @cpumap_bitmap
- * bit set are written to. On return, @cpumap_bitmap is modified so that any
- * non-existent CPUs are cleared. Such CPUs have their @idletime array entry
- * cleared.
- */
-#define XENPF_getidletime 53
-struct xenpf_getidletime {
- /* IN/OUT variables */
- /* IN: CPUs to interrogate; OUT: subset of IN which are present */
- XEN_GUEST_HANDLE(uint8) cpumap_bitmap;
- /* IN variables */
- /* Size of cpumap bitmap. */
- uint32_t cpumap_nr_cpus;
- /* Must be indexable for every cpu in cpumap_bitmap. */
- XEN_GUEST_HANDLE(uint64) idletime;
- /* OUT variables */
- /* System time when the idletime snapshots were taken. */
- uint64_t now;
-};
-typedef struct xenpf_getidletime xenpf_getidletime_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_getidletime_t);
-
-#define XENPF_set_processor_pminfo 54
-
-/* ability bits */
-#define XEN_PROCESSOR_PM_CX 1
-#define XEN_PROCESSOR_PM_PX 2
-#define XEN_PROCESSOR_PM_TX 4
-
-/* cmd type */
-#define XEN_PM_CX 0
-#define XEN_PM_PX 1
-#define XEN_PM_TX 2
-#define XEN_PM_PDC 3
-
-/* Px sub info type */
-#define XEN_PX_PCT 1
-#define XEN_PX_PSS 2
-#define XEN_PX_PPC 4
-#define XEN_PX_PSD 8
-
-struct xen_power_register {
- uint32_t space_id;
- uint32_t bit_width;
- uint32_t bit_offset;
- uint32_t access_size;
- uint64_t address;
-};
-
-struct xen_processor_csd {
- uint32_t domain; /* domain number of one dependent group */
- uint32_t coord_type; /* coordination type */
- uint32_t num; /* number of processors in same domain */
-};
-typedef struct xen_processor_csd xen_processor_csd_t;
-DEFINE_XEN_GUEST_HANDLE(xen_processor_csd_t);
-
-struct xen_processor_cx {
- struct xen_power_register reg; /* GAS for Cx trigger register */
- uint8_t type; /* cstate value, c0: 0, c1: 1, ... */
- uint32_t latency; /* worst latency (ms) to enter/exit this cstate */
- uint32_t power; /* average power consumption(mW) */
- uint32_t dpcnt; /* number of dependency entries */
- XEN_GUEST_HANDLE(xen_processor_csd_t) dp; /* NULL if no dependency */
-};
-typedef struct xen_processor_cx xen_processor_cx_t;
-DEFINE_XEN_GUEST_HANDLE(xen_processor_cx_t);
-
-struct xen_processor_flags {
- uint32_t bm_control:1;
- uint32_t bm_check:1;
- uint32_t has_cst:1;
- uint32_t power_setup_done:1;
- uint32_t bm_rld_set:1;
-};
-
-struct xen_processor_power {
- uint32_t count; /* number of C state entries in array below */
- struct xen_processor_flags flags; /* global flags of this processor */
- XEN_GUEST_HANDLE(xen_processor_cx_t) states; /* supported c states */
-};
-
-struct xen_pct_register {
- uint8_t descriptor;
- uint16_t length;
- uint8_t space_id;
- uint8_t bit_width;
- uint8_t bit_offset;
- uint8_t reserved;
- uint64_t address;
-};
-
-struct xen_processor_px {
- uint64_t core_frequency; /* megahertz */
- uint64_t power; /* milliWatts */
- uint64_t transition_latency; /* microseconds */
- uint64_t bus_master_latency; /* microseconds */
- uint64_t control; /* control value */
- uint64_t status; /* success indicator */
-};
-typedef struct xen_processor_px xen_processor_px_t;
-DEFINE_XEN_GUEST_HANDLE(xen_processor_px_t);
-
-struct xen_psd_package {
- uint64_t num_entries;
- uint64_t revision;
- uint64_t domain;
- uint64_t coord_type;
- uint64_t num_processors;
-};
-
-struct xen_processor_performance {
- uint32_t flags; /* flag for Px sub info type */
- uint32_t platform_limit; /* Platform limitation on freq usage */
- struct xen_pct_register control_register;
- struct xen_pct_register status_register;
- uint32_t state_count; /* total available performance states */
- XEN_GUEST_HANDLE(xen_processor_px_t) states;
- struct xen_psd_package domain_info;
- uint32_t shared_type; /* coordination type of this processor */
-};
-typedef struct xen_processor_performance xen_processor_performance_t;
-DEFINE_XEN_GUEST_HANDLE(xen_processor_performance_t);
-
-struct xenpf_set_processor_pminfo {
- /* IN variables */
- uint32_t id; /* ACPI CPU ID */
- uint32_t type; /* {XEN_PM_CX, XEN_PM_PX} */
- union {
- struct xen_processor_power power;/* Cx: _CST/_CSD */
- struct xen_processor_performance perf; /* Px: _PPC/_PCT/_PSS/_PSD */
- XEN_GUEST_HANDLE(uint32) pdc; /* _PDC */
- } u;
-};
-typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_set_processor_pminfo_t);
-
-#define XENPF_get_cpuinfo 55
-struct xenpf_pcpuinfo {
- /* IN */
- uint32_t xen_cpuid;
- /* OUT */
- /* The maxium cpu_id that is present */
- uint32_t max_present;
-#define XEN_PCPU_FLAGS_ONLINE 1
- /* Correponding xen_cpuid is not present*/
-#define XEN_PCPU_FLAGS_INVALID 2
- uint32_t flags;
- uint32_t apic_id;
- uint32_t acpi_id;
-};
-typedef struct xenpf_pcpuinfo xenpf_pcpuinfo_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_pcpuinfo_t);
-
-#define XENPF_get_cpu_version 48
-struct xenpf_pcpu_version {
- /* IN */
- uint32_t xen_cpuid;
- /* OUT */
- /* The maxium cpu_id that is present */
- uint32_t max_present;
- char vendor_id[12];
- uint32_t family;
- uint32_t model;
- uint32_t stepping;
-};
-typedef struct xenpf_pcpu_version xenpf_pcpu_version_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_pcpu_version_t);
-
-#define XENPF_cpu_online 56
-#define XENPF_cpu_offline 57
-struct xenpf_cpu_ol
-{
- uint32_t cpuid;
-};
-typedef struct xenpf_cpu_ol xenpf_cpu_ol_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_cpu_ol_t);
-
-#define XENPF_cpu_hotadd 58
-struct xenpf_cpu_hotadd
-{
- uint32_t apic_id;
- uint32_t acpi_id;
- uint32_t pxm;
-};
-
-#define XENPF_mem_hotadd 59
-struct xenpf_mem_hotadd
-{
- uint64_t spfn;
- uint64_t epfn;
- uint32_t pxm;
- uint32_t flags;
-};
-
-#define XENPF_core_parking 60
-
-#define XEN_CORE_PARKING_SET 1
-#define XEN_CORE_PARKING_GET 2
-struct xenpf_core_parking {
- /* IN variables */
- uint32_t type;
- /* IN variables: set cpu nums expected to be idled */
- /* OUT variables: get cpu nums actually be idled */
- uint32_t idle_nums;
-};
-typedef struct xenpf_core_parking xenpf_core_parking_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_core_parking_t);
-
-/*
- * Access generic platform resources(e.g., accessing MSR, port I/O, etc)
- * in unified way. Batch resource operations in one call are supported and
- * they are always non-preemptible and executed in their original order.
- * The batch itself returns a negative integer for general errors, or a
- * non-negative integer for the number of successful operations. For the latter
- * case, the @ret in the failed entry (if any) indicates the exact error.
- */
-#define XENPF_resource_op 61
-
-#define XEN_RESOURCE_OP_MSR_READ 0
-#define XEN_RESOURCE_OP_MSR_WRITE 1
-
-struct xenpf_resource_entry {
- union {
- uint32_t cmd; /* IN: XEN_RESOURCE_OP_* */
- int32_t ret; /* OUT: return value for failed entry */
- } u;
- uint32_t rsvd; /* IN: padding and must be zero */
- uint64_t idx; /* IN: resource address to access */
- uint64_t val; /* IN/OUT: resource value to set/get */
-};
-typedef struct xenpf_resource_entry xenpf_resource_entry_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_resource_entry_t);
-
-struct xenpf_resource_op {
- uint32_t nr_entries; /* number of resource entry */
- uint32_t cpu; /* which cpu to run */
- XEN_GUEST_HANDLE(xenpf_resource_entry_t) entries;
-};
-typedef struct xenpf_resource_op xenpf_resource_op_t;
-DEFINE_XEN_GUEST_HANDLE(xenpf_resource_op_t);
-
-/*
- * ` enum neg_errnoval
- * ` HYPERVISOR_platform_op(const struct xen_platform_op*);
- */
-struct xen_platform_op {
- uint32_t cmd;
- uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
- union {
- struct xenpf_settime settime;
- struct xenpf_add_memtype add_memtype;
- struct xenpf_del_memtype del_memtype;
- struct xenpf_read_memtype read_memtype;
- struct xenpf_microcode_update microcode;
- struct xenpf_platform_quirk platform_quirk;
- struct xenpf_efi_runtime_call efi_runtime_call;
- struct xenpf_firmware_info firmware_info;
- struct xenpf_enter_acpi_sleep enter_acpi_sleep;
- struct xenpf_change_freq change_freq;
- struct xenpf_getidletime getidletime;
- struct xenpf_set_processor_pminfo set_pminfo;
- struct xenpf_pcpuinfo pcpu_info;
- struct xenpf_pcpu_version pcpu_version;
- struct xenpf_cpu_ol cpu_ol;
- struct xenpf_cpu_hotadd cpu_add;
- struct xenpf_mem_hotadd mem_add;
- struct xenpf_core_parking core_parking;
- struct xenpf_resource_op resource_op;
- uint8_t pad[128];
- } u;
-};
-typedef struct xen_platform_op xen_platform_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_platform_op_t);
-
-#endif /* __XEN_PUBLIC_PLATFORM_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * sched.h
- *
- * Scheduler state interactions
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
- */
-
-#ifndef __XEN_PUBLIC_SCHED_H__
-#define __XEN_PUBLIC_SCHED_H__
-
-#include "event_channel.h"
-
-/*
- * `incontents 150 sched Guest Scheduler Operations
- *
- * The SCHEDOP interface provides mechanisms for a guest to interact
- * with the scheduler, including yield, blocking and shutting itself
- * down.
- */
-
-/*
- * The prototype for this hypercall is:
- * ` long HYPERVISOR_sched_op(enum sched_op cmd, void *arg, ...)
- *
- * @cmd == SCHEDOP_??? (scheduler operation).
- * @arg == Operation-specific extra argument(s), as described below.
- * ... == Additional Operation-specific extra arguments, described below.
- *
- * Versions of Xen prior to 3.0.2 provided only the following legacy version
- * of this hypercall, supporting only the commands yield, block and shutdown:
- * long sched_op(int cmd, unsigned long arg)
- * @cmd == SCHEDOP_??? (scheduler operation).
- * @arg == 0 (SCHEDOP_yield and SCHEDOP_block)
- * == SHUTDOWN_* code (SCHEDOP_shutdown)
- *
- * This legacy version is available to new guests as:
- * ` long HYPERVISOR_sched_op_compat(enum sched_op cmd, unsigned long arg)
- */
-
-/* ` enum sched_op { // SCHEDOP_* => struct sched_* */
-/*
- * Voluntarily yield the CPU.
- * @arg == NULL.
- */
-#define SCHEDOP_yield 0
-
-/*
- * Block execution of this VCPU until an event is received for processing.
- * If called with event upcalls masked, this operation will atomically
- * reenable event delivery and check for pending events before blocking the
- * VCPU. This avoids a "wakeup waiting" race.
- * @arg == NULL.
- */
-#define SCHEDOP_block 1
-
-/*
- * Halt execution of this domain (all VCPUs) and notify the system controller.
- * @arg == pointer to sched_shutdown_t structure.
- *
- * If the sched_shutdown_t reason is SHUTDOWN_suspend then
- * x86 PV guests must also set RDX (EDX for 32-bit guests) to the MFN
- * of the guest's start info page. RDX/EDX is the third hypercall
- * argument.
- *
- * In addition, which reason is SHUTDOWN_suspend this hypercall
- * returns 1 if suspend was cancelled or the domain was merely
- * checkpointed, and 0 if it is resuming in a new domain.
- */
-#define SCHEDOP_shutdown 2
-
-/*
- * Poll a set of event-channel ports. Return when one or more are pending. An
- * optional timeout may be specified.
- * @arg == pointer to sched_poll_t structure.
- */
-#define SCHEDOP_poll 3
-
-/*
- * Declare a shutdown for another domain. The main use of this function is
- * in interpreting shutdown requests and reasons for fully-virtualized
- * domains. A para-virtualized domain may use SCHEDOP_shutdown directly.
- * @arg == pointer to sched_remote_shutdown_t structure.
- */
-#define SCHEDOP_remote_shutdown 4
-
-/*
- * Latch a shutdown code, so that when the domain later shuts down it
- * reports this code to the control tools.
- * @arg == sched_shutdown_t, as for SCHEDOP_shutdown.
- */
-#define SCHEDOP_shutdown_code 5
-
-/*
- * Setup, poke and destroy a domain watchdog timer.
- * @arg == pointer to sched_watchdog_t structure.
- * With id == 0, setup a domain watchdog timer to cause domain shutdown
- * after timeout, returns watchdog id.
- * With id != 0 and timeout == 0, destroy domain watchdog timer.
- * With id != 0 and timeout != 0, poke watchdog timer and set new timeout.
- */
-#define SCHEDOP_watchdog 6
-/* ` } */
-
-struct sched_shutdown {
- unsigned int reason; /* SHUTDOWN_* => enum sched_shutdown_reason */
-};
-typedef struct sched_shutdown sched_shutdown_t;
-DEFINE_XEN_GUEST_HANDLE(sched_shutdown_t);
-
-struct sched_poll {
- XEN_GUEST_HANDLE(evtchn_port_t) ports;
- unsigned int nr_ports;
- uint64_t timeout;
-};
-typedef struct sched_poll sched_poll_t;
-DEFINE_XEN_GUEST_HANDLE(sched_poll_t);
-
-struct sched_remote_shutdown {
- domid_t domain_id; /* Remote domain ID */
- unsigned int reason; /* SHUTDOWN_* => enum sched_shutdown_reason */
-};
-typedef struct sched_remote_shutdown sched_remote_shutdown_t;
-DEFINE_XEN_GUEST_HANDLE(sched_remote_shutdown_t);
-
-struct sched_watchdog {
- uint32_t id; /* watchdog ID */
- uint32_t timeout; /* timeout */
-};
-typedef struct sched_watchdog sched_watchdog_t;
-DEFINE_XEN_GUEST_HANDLE(sched_watchdog_t);
-
-/*
- * Reason codes for SCHEDOP_shutdown. These may be interpreted by control
- * software to determine the appropriate action. For the most part, Xen does
- * not care about the shutdown code.
- */
-/* ` enum sched_shutdown_reason { */
-#define SHUTDOWN_poweroff 0 /* Domain exited normally. Clean up and kill. */
-#define SHUTDOWN_reboot 1 /* Clean up, kill, and then restart. */
-#define SHUTDOWN_suspend 2 /* Clean up, save suspend info, kill. */
-#define SHUTDOWN_crash 3 /* Tell controller we've crashed. */
-#define SHUTDOWN_watchdog 4 /* Restart because watchdog time expired. */
-#define SHUTDOWN_MAX 4 /* Maximum valid shutdown reason. */
-/* ` } */
-
-#endif /* __XEN_PUBLIC_SCHED_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * sysctl.h
- *
- * System management operations. For use by node control stack.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2002-2006, K Fraser
- */
-
-#ifndef __XEN_PUBLIC_SYSCTL_H__
-#define __XEN_PUBLIC_SYSCTL_H__
-
-#if !defined(__XEN__) && !defined(__XEN_TOOLS__)
-#error "sysctl operations are intended for use by node control tools only"
-#endif
-
-#include "xen.h"
-#include "domctl.h"
-
-#define XEN_SYSCTL_INTERFACE_VERSION 0x0000000B
-
-/*
- * Read console content from Xen buffer ring.
- */
-/* XEN_SYSCTL_readconsole */
-struct xen_sysctl_readconsole {
- /* IN: Non-zero -> clear after reading. */
- uint8_t clear;
- /* IN: Non-zero -> start index specified by @index field. */
- uint8_t incremental;
- uint8_t pad0, pad1;
- /*
- * IN: Start index for consuming from ring buffer (if @incremental);
- * OUT: End index after consuming from ring buffer.
- */
- uint32_t index;
- /* IN: Virtual address to write console data. */
- XEN_GUEST_HANDLE_64(char) buffer;
- /* IN: Size of buffer; OUT: Bytes written to buffer. */
- uint32_t count;
-};
-typedef struct xen_sysctl_readconsole xen_sysctl_readconsole_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_readconsole_t);
-
-/* Get trace buffers machine base address */
-/* XEN_SYSCTL_tbuf_op */
-struct xen_sysctl_tbuf_op {
- /* IN variables */
-#define XEN_SYSCTL_TBUFOP_get_info 0
-#define XEN_SYSCTL_TBUFOP_set_cpu_mask 1
-#define XEN_SYSCTL_TBUFOP_set_evt_mask 2
-#define XEN_SYSCTL_TBUFOP_set_size 3
-#define XEN_SYSCTL_TBUFOP_enable 4
-#define XEN_SYSCTL_TBUFOP_disable 5
- uint32_t cmd;
- /* IN/OUT variables */
- struct xenctl_bitmap cpu_mask;
- uint32_t evt_mask;
- /* OUT variables */
- uint64_aligned_t buffer_mfn;
- uint32_t size; /* Also an IN variable! */
-};
-typedef struct xen_sysctl_tbuf_op xen_sysctl_tbuf_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_tbuf_op_t);
-
-/*
- * Get physical information about the host machine
- */
-/* XEN_SYSCTL_physinfo */
- /* (x86) The platform supports HVM guests. */
-#define _XEN_SYSCTL_PHYSCAP_hvm 0
-#define XEN_SYSCTL_PHYSCAP_hvm (1u<<_XEN_SYSCTL_PHYSCAP_hvm)
- /* (x86) The platform supports HVM-guest direct access to I/O devices. */
-#define _XEN_SYSCTL_PHYSCAP_hvm_directio 1
-#define XEN_SYSCTL_PHYSCAP_hvm_directio (1u<<_XEN_SYSCTL_PHYSCAP_hvm_directio)
-struct xen_sysctl_physinfo {
- uint32_t threads_per_core;
- uint32_t cores_per_socket;
- uint32_t nr_cpus; /* # CPUs currently online */
- uint32_t max_cpu_id; /* Largest possible CPU ID on this host */
- uint32_t nr_nodes; /* # nodes currently online */
- uint32_t max_node_id; /* Largest possible node ID on this host */
- uint32_t cpu_khz;
- uint64_aligned_t total_pages;
- uint64_aligned_t free_pages;
- uint64_aligned_t scrub_pages;
- uint64_aligned_t outstanding_pages;
- uint32_t hw_cap[8];
-
- /* XEN_SYSCTL_PHYSCAP_??? */
- uint32_t capabilities;
-};
-typedef struct xen_sysctl_physinfo xen_sysctl_physinfo_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_physinfo_t);
-
-/*
- * Get the ID of the current scheduler.
- */
-/* XEN_SYSCTL_sched_id */
-struct xen_sysctl_sched_id {
- /* OUT variable */
- uint32_t sched_id;
-};
-typedef struct xen_sysctl_sched_id xen_sysctl_sched_id_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_sched_id_t);
-
-/* Interface for controlling Xen software performance counters. */
-/* XEN_SYSCTL_perfc_op */
-/* Sub-operations: */
-#define XEN_SYSCTL_PERFCOP_reset 1 /* Reset all counters to zero. */
-#define XEN_SYSCTL_PERFCOP_query 2 /* Get perfctr information. */
-struct xen_sysctl_perfc_desc {
- char name[80]; /* name of perf counter */
- uint32_t nr_vals; /* number of values for this counter */
-};
-typedef struct xen_sysctl_perfc_desc xen_sysctl_perfc_desc_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t);
-typedef uint32_t xen_sysctl_perfc_val_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t);
-
-struct xen_sysctl_perfc_op {
- /* IN variables. */
- uint32_t cmd; /* XEN_SYSCTL_PERFCOP_??? */
- /* OUT variables. */
- uint32_t nr_counters; /* number of counters description */
- uint32_t nr_vals; /* number of values */
- /* counter information (or NULL) */
- XEN_GUEST_HANDLE_64(xen_sysctl_perfc_desc_t) desc;
- /* counter values (or NULL) */
- XEN_GUEST_HANDLE_64(xen_sysctl_perfc_val_t) val;
-};
-typedef struct xen_sysctl_perfc_op xen_sysctl_perfc_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_op_t);
-
-/* XEN_SYSCTL_getdomaininfolist */
-struct xen_sysctl_getdomaininfolist {
- /* IN variables. */
- domid_t first_domain;
- uint32_t max_domains;
- XEN_GUEST_HANDLE_64(xen_domctl_getdomaininfo_t) buffer;
- /* OUT variables. */
- uint32_t num_domains;
-};
-typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t);
-
-/* Inject debug keys into Xen. */
-/* XEN_SYSCTL_debug_keys */
-struct xen_sysctl_debug_keys {
- /* IN variables. */
- XEN_GUEST_HANDLE_64(char) keys;
- uint32_t nr_keys;
-};
-typedef struct xen_sysctl_debug_keys xen_sysctl_debug_keys_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_debug_keys_t);
-
-/* Get physical CPU information. */
-/* XEN_SYSCTL_getcpuinfo */
-struct xen_sysctl_cpuinfo {
- uint64_aligned_t idletime;
-};
-typedef struct xen_sysctl_cpuinfo xen_sysctl_cpuinfo_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpuinfo_t);
-struct xen_sysctl_getcpuinfo {
- /* IN variables. */
- uint32_t max_cpus;
- XEN_GUEST_HANDLE_64(xen_sysctl_cpuinfo_t) info;
- /* OUT variables. */
- uint32_t nr_cpus;
-};
-typedef struct xen_sysctl_getcpuinfo xen_sysctl_getcpuinfo_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getcpuinfo_t);
-
-/* XEN_SYSCTL_availheap */
-struct xen_sysctl_availheap {
- /* IN variables. */
- uint32_t min_bitwidth; /* Smallest address width (zero if don't care). */
- uint32_t max_bitwidth; /* Largest address width (zero if don't care). */
- int32_t node; /* NUMA node of interest (-1 for all nodes). */
- /* OUT variables. */
- uint64_aligned_t avail_bytes;/* Bytes available in the specified region. */
-};
-typedef struct xen_sysctl_availheap xen_sysctl_availheap_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_availheap_t);
-
-/* XEN_SYSCTL_get_pmstat */
-struct pm_px_val {
- uint64_aligned_t freq; /* Px core frequency */
- uint64_aligned_t residency; /* Px residency time */
- uint64_aligned_t count; /* Px transition count */
-};
-typedef struct pm_px_val pm_px_val_t;
-DEFINE_XEN_GUEST_HANDLE(pm_px_val_t);
-
-struct pm_px_stat {
- uint8_t total; /* total Px states */
- uint8_t usable; /* usable Px states */
- uint8_t last; /* last Px state */
- uint8_t cur; /* current Px state */
- XEN_GUEST_HANDLE_64(uint64) trans_pt; /* Px transition table */
- XEN_GUEST_HANDLE_64(pm_px_val_t) pt;
-};
-typedef struct pm_px_stat pm_px_stat_t;
-DEFINE_XEN_GUEST_HANDLE(pm_px_stat_t);
-
-struct pm_cx_stat {
- uint32_t nr; /* entry nr in triggers & residencies, including C0 */
- uint32_t last; /* last Cx state */
- uint64_aligned_t idle_time; /* idle time from boot */
- XEN_GUEST_HANDLE_64(uint64) triggers; /* Cx trigger counts */
- XEN_GUEST_HANDLE_64(uint64) residencies; /* Cx residencies */
- uint32_t nr_pc; /* entry nr in pc[] */
- uint32_t nr_cc; /* entry nr in cc[] */
- /*
- * These two arrays may (and generally will) have unused slots; slots not
- * having a corresponding hardware register will not be written by the
- * hypervisor. It is therefore up to the caller to put a suitable sentinel
- * into all slots before invoking the function.
- * Indexing is 1-biased (PC1/CC1 being at index 0).
- */
- XEN_GUEST_HANDLE_64(uint64) pc;
- XEN_GUEST_HANDLE_64(uint64) cc;
-};
-
-struct xen_sysctl_get_pmstat {
-#define PMSTAT_CATEGORY_MASK 0xf0
-#define PMSTAT_PX 0x10
-#define PMSTAT_CX 0x20
-#define PMSTAT_get_max_px (PMSTAT_PX | 0x1)
-#define PMSTAT_get_pxstat (PMSTAT_PX | 0x2)
-#define PMSTAT_reset_pxstat (PMSTAT_PX | 0x3)
-#define PMSTAT_get_max_cx (PMSTAT_CX | 0x1)
-#define PMSTAT_get_cxstat (PMSTAT_CX | 0x2)
-#define PMSTAT_reset_cxstat (PMSTAT_CX | 0x3)
- uint32_t type;
- uint32_t cpuid;
- union {
- struct pm_px_stat getpx;
- struct pm_cx_stat getcx;
- /* other struct for tx, etc */
- } u;
-};
-typedef struct xen_sysctl_get_pmstat xen_sysctl_get_pmstat_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_get_pmstat_t);
-
-/* XEN_SYSCTL_cpu_hotplug */
-struct xen_sysctl_cpu_hotplug {
- /* IN variables */
- uint32_t cpu; /* Physical cpu. */
-#define XEN_SYSCTL_CPU_HOTPLUG_ONLINE 0
-#define XEN_SYSCTL_CPU_HOTPLUG_OFFLINE 1
- uint32_t op; /* hotplug opcode */
-};
-typedef struct xen_sysctl_cpu_hotplug xen_sysctl_cpu_hotplug_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpu_hotplug_t);
-
-/*
- * Get/set xen power management, include
- * 1. cpufreq governors and related parameters
- */
-/* XEN_SYSCTL_pm_op */
-struct xen_userspace {
- uint32_t scaling_setspeed;
-};
-typedef struct xen_userspace xen_userspace_t;
-
-struct xen_ondemand {
- uint32_t sampling_rate_max;
- uint32_t sampling_rate_min;
-
- uint32_t sampling_rate;
- uint32_t up_threshold;
-};
-typedef struct xen_ondemand xen_ondemand_t;
-
-/*
- * cpufreq para name of this structure named
- * same as sysfs file name of native linux
- */
-#define CPUFREQ_NAME_LEN 16
-struct xen_get_cpufreq_para {
- /* IN/OUT variable */
- uint32_t cpu_num;
- uint32_t freq_num;
- uint32_t gov_num;
-
- /* for all governors */
- /* OUT variable */
- XEN_GUEST_HANDLE_64(uint32) affected_cpus;
- XEN_GUEST_HANDLE_64(uint32) scaling_available_frequencies;
- XEN_GUEST_HANDLE_64(char) scaling_available_governors;
- char scaling_driver[CPUFREQ_NAME_LEN];
-
- uint32_t cpuinfo_cur_freq;
- uint32_t cpuinfo_max_freq;
- uint32_t cpuinfo_min_freq;
- uint32_t scaling_cur_freq;
-
- char scaling_governor[CPUFREQ_NAME_LEN];
- uint32_t scaling_max_freq;
- uint32_t scaling_min_freq;
-
- /* for specific governor */
- union {
- struct xen_userspace userspace;
- struct xen_ondemand ondemand;
- } u;
-
- int32_t turbo_enabled;
-};
-
-struct xen_set_cpufreq_gov {
- char scaling_governor[CPUFREQ_NAME_LEN];
-};
-
-struct xen_set_cpufreq_para {
- #define SCALING_MAX_FREQ 1
- #define SCALING_MIN_FREQ 2
- #define SCALING_SETSPEED 3
- #define SAMPLING_RATE 4
- #define UP_THRESHOLD 5
-
- uint32_t ctrl_type;
- uint32_t ctrl_value;
-};
-
-struct xen_sysctl_pm_op {
- #define PM_PARA_CATEGORY_MASK 0xf0
- #define CPUFREQ_PARA 0x10
-
- /* cpufreq command type */
- #define GET_CPUFREQ_PARA (CPUFREQ_PARA | 0x01)
- #define SET_CPUFREQ_GOV (CPUFREQ_PARA | 0x02)
- #define SET_CPUFREQ_PARA (CPUFREQ_PARA | 0x03)
- #define GET_CPUFREQ_AVGFREQ (CPUFREQ_PARA | 0x04)
-
- /* set/reset scheduler power saving option */
- #define XEN_SYSCTL_pm_op_set_sched_opt_smt 0x21
-
- /* cpuidle max_cstate access command */
- #define XEN_SYSCTL_pm_op_get_max_cstate 0x22
- #define XEN_SYSCTL_pm_op_set_max_cstate 0x23
-
- /* set scheduler migration cost value */
- #define XEN_SYSCTL_pm_op_set_vcpu_migration_delay 0x24
- #define XEN_SYSCTL_pm_op_get_vcpu_migration_delay 0x25
-
- /* enable/disable turbo mode when in dbs governor */
- #define XEN_SYSCTL_pm_op_enable_turbo 0x26
- #define XEN_SYSCTL_pm_op_disable_turbo 0x27
-
- uint32_t cmd;
- uint32_t cpuid;
- union {
- struct xen_get_cpufreq_para get_para;
- struct xen_set_cpufreq_gov set_gov;
- struct xen_set_cpufreq_para set_para;
- uint64_aligned_t get_avgfreq;
- uint32_t set_sched_opt_smt;
- uint32_t get_max_cstate;
- uint32_t set_max_cstate;
- uint32_t get_vcpu_migration_delay;
- uint32_t set_vcpu_migration_delay;
- } u;
-};
-
-/* XEN_SYSCTL_page_offline_op */
-struct xen_sysctl_page_offline_op {
- /* IN: range of page to be offlined */
-#define sysctl_page_offline 1
-#define sysctl_page_online 2
-#define sysctl_query_page_offline 3
- uint32_t cmd;
- uint32_t start;
- uint32_t end;
- /* OUT: result of page offline request */
- /*
- * bit 0~15: result flags
- * bit 16~31: owner
- */
- XEN_GUEST_HANDLE(uint32) status;
-};
-
-#define PG_OFFLINE_STATUS_MASK (0xFFUL)
-
-/* The result is invalid, i.e. HV does not handle it */
-#define PG_OFFLINE_INVALID (0x1UL << 0)
-
-#define PG_OFFLINE_OFFLINED (0x1UL << 1)
-#define PG_OFFLINE_PENDING (0x1UL << 2)
-#define PG_OFFLINE_FAILED (0x1UL << 3)
-#define PG_OFFLINE_AGAIN (0x1UL << 4)
-
-#define PG_ONLINE_FAILED PG_OFFLINE_FAILED
-#define PG_ONLINE_ONLINED PG_OFFLINE_OFFLINED
-
-#define PG_OFFLINE_STATUS_OFFLINED (0x1UL << 1)
-#define PG_OFFLINE_STATUS_ONLINE (0x1UL << 2)
-#define PG_OFFLINE_STATUS_OFFLINE_PENDING (0x1UL << 3)
-#define PG_OFFLINE_STATUS_BROKEN (0x1UL << 4)
-
-#define PG_OFFLINE_MISC_MASK (0xFFUL << 4)
-
-/* valid when PG_OFFLINE_FAILED or PG_OFFLINE_PENDING */
-#define PG_OFFLINE_XENPAGE (0x1UL << 8)
-#define PG_OFFLINE_DOM0PAGE (0x1UL << 9)
-#define PG_OFFLINE_ANONYMOUS (0x1UL << 10)
-#define PG_OFFLINE_NOT_CONV_RAM (0x1UL << 11)
-#define PG_OFFLINE_OWNED (0x1UL << 12)
-
-#define PG_OFFLINE_BROKEN (0x1UL << 13)
-#define PG_ONLINE_BROKEN PG_OFFLINE_BROKEN
-
-#define PG_OFFLINE_OWNER_SHIFT 16
-
-/* XEN_SYSCTL_lockprof_op */
-/* Sub-operations: */
-#define XEN_SYSCTL_LOCKPROF_reset 1 /* Reset all profile data to zero. */
-#define XEN_SYSCTL_LOCKPROF_query 2 /* Get lock profile information. */
-/* Record-type: */
-#define LOCKPROF_TYPE_GLOBAL 0 /* global lock, idx meaningless */
-#define LOCKPROF_TYPE_PERDOM 1 /* per-domain lock, idx is domid */
-#define LOCKPROF_TYPE_N 2 /* number of types */
-struct xen_sysctl_lockprof_data {
- char name[40]; /* lock name (may include up to 2 %d specifiers) */
- int32_t type; /* LOCKPROF_TYPE_??? */
- int32_t idx; /* index (e.g. domain id) */
- uint64_aligned_t lock_cnt; /* # of locking succeeded */
- uint64_aligned_t block_cnt; /* # of wait for lock */
- uint64_aligned_t lock_time; /* nsecs lock held */
- uint64_aligned_t block_time; /* nsecs waited for lock */
-};
-typedef struct xen_sysctl_lockprof_data xen_sysctl_lockprof_data_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_lockprof_data_t);
-struct xen_sysctl_lockprof_op {
- /* IN variables. */
- uint32_t cmd; /* XEN_SYSCTL_LOCKPROF_??? */
- uint32_t max_elem; /* size of output buffer */
- /* OUT variables (query only). */
- uint32_t nr_elem; /* number of elements available */
- uint64_aligned_t time; /* nsecs of profile measurement */
- /* profile information (or NULL) */
- XEN_GUEST_HANDLE_64(xen_sysctl_lockprof_data_t) data;
-};
-typedef struct xen_sysctl_lockprof_op xen_sysctl_lockprof_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_lockprof_op_t);
-
-/* XEN_SYSCTL_topologyinfo */
-#define INVALID_TOPOLOGY_ID (~0U)
-struct xen_sysctl_topologyinfo {
- /*
- * IN: maximum addressable entry in the caller-provided arrays.
- * OUT: largest cpu identifier in the system.
- * If OUT is greater than IN then the arrays are truncated!
- * If OUT is leass than IN then the array tails are not written by sysctl.
- */
- uint32_t max_cpu_index;
-
- /*
- * If not NULL, these arrays are filled with core/socket/node identifier
- * for each cpu.
- * If a cpu has no core/socket/node information (e.g., cpu not present)
- * then the sentinel value ~0u is written to each array.
- * The number of array elements written by the sysctl is:
- * min(@max_cpu_index_IN,@max_cpu_index_OUT)+1
- */
- XEN_GUEST_HANDLE_64(uint32) cpu_to_core;
- XEN_GUEST_HANDLE_64(uint32) cpu_to_socket;
- XEN_GUEST_HANDLE_64(uint32) cpu_to_node;
-};
-typedef struct xen_sysctl_topologyinfo xen_sysctl_topologyinfo_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_topologyinfo_t);
-
-/* XEN_SYSCTL_numainfo */
-#define INVALID_NUMAINFO_ID (~0U)
-struct xen_sysctl_numainfo {
- /*
- * IN: maximum addressable entry in the caller-provided arrays.
- * OUT: largest node identifier in the system.
- * If OUT is greater than IN then the arrays are truncated!
- */
- uint32_t max_node_index;
-
- /* NB. Entries are 0 if node is not present. */
- XEN_GUEST_HANDLE_64(uint64) node_to_memsize;
- XEN_GUEST_HANDLE_64(uint64) node_to_memfree;
-
- /*
- * Array, of size (max_node_index+1)^2, listing memory access distances
- * between nodes. If an entry has no node distance information (e.g., node
- * not present) then the value ~0u is written.
- *
- * Note that the array rows must be indexed by multiplying by the minimum
- * of the caller-provided max_node_index and the returned value of
- * max_node_index. That is, if the largest node index in the system is
- * smaller than the caller can handle, a smaller 2-d array is constructed
- * within the space provided by the caller. When this occurs, trailing
- * space provided by the caller is not modified. If the largest node index
- * in the system is larger than the caller can handle, then a 2-d array of
- * the maximum size handleable by the caller is constructed.
- */
- XEN_GUEST_HANDLE_64(uint32) node_to_node_distance;
-};
-typedef struct xen_sysctl_numainfo xen_sysctl_numainfo_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_numainfo_t);
-
-/* XEN_SYSCTL_cpupool_op */
-#define XEN_SYSCTL_CPUPOOL_OP_CREATE 1 /* C */
-#define XEN_SYSCTL_CPUPOOL_OP_DESTROY 2 /* D */
-#define XEN_SYSCTL_CPUPOOL_OP_INFO 3 /* I */
-#define XEN_SYSCTL_CPUPOOL_OP_ADDCPU 4 /* A */
-#define XEN_SYSCTL_CPUPOOL_OP_RMCPU 5 /* R */
-#define XEN_SYSCTL_CPUPOOL_OP_MOVEDOMAIN 6 /* M */
-#define XEN_SYSCTL_CPUPOOL_OP_FREEINFO 7 /* F */
-#define XEN_SYSCTL_CPUPOOL_PAR_ANY 0xFFFFFFFF
-struct xen_sysctl_cpupool_op {
- uint32_t op; /* IN */
- uint32_t cpupool_id; /* IN: CDIARM OUT: CI */
- uint32_t sched_id; /* IN: C OUT: I */
- uint32_t domid; /* IN: M */
- uint32_t cpu; /* IN: AR */
- uint32_t n_dom; /* OUT: I */
- struct xenctl_bitmap cpumap; /* OUT: IF */
-};
-typedef struct xen_sysctl_cpupool_op xen_sysctl_cpupool_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpupool_op_t);
-
-#define ARINC653_MAX_DOMAINS_PER_SCHEDULE 64
-/*
- * This structure is used to pass a new ARINC653 schedule from a
- * privileged domain (ie dom0) to Xen.
- */
-struct xen_sysctl_arinc653_schedule {
- /* major_frame holds the time for the new schedule's major frame
- * in nanoseconds. */
- uint64_aligned_t major_frame;
- /* num_sched_entries holds how many of the entries in the
- * sched_entries[] array are valid. */
- uint8_t num_sched_entries;
- /* The sched_entries array holds the actual schedule entries. */
- struct {
- /* dom_handle must match a domain's UUID */
- xen_domain_handle_t dom_handle;
- /* If a domain has multiple VCPUs, vcpu_id specifies which one
- * this schedule entry applies to. It should be set to 0 if
- * there is only one VCPU for the domain. */
- unsigned int vcpu_id;
- /* runtime specifies the amount of time that should be allocated
- * to this VCPU per major frame. It is specified in nanoseconds */
- uint64_aligned_t runtime;
- } sched_entries[ARINC653_MAX_DOMAINS_PER_SCHEDULE];
-};
-typedef struct xen_sysctl_arinc653_schedule xen_sysctl_arinc653_schedule_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_arinc653_schedule_t);
-
-struct xen_sysctl_credit_schedule {
- /* Length of timeslice in milliseconds */
-#define XEN_SYSCTL_CSCHED_TSLICE_MAX 1000
-#define XEN_SYSCTL_CSCHED_TSLICE_MIN 1
- unsigned tslice_ms;
- /* Rate limit (minimum timeslice) in microseconds */
-#define XEN_SYSCTL_SCHED_RATELIMIT_MAX 500000
-#define XEN_SYSCTL_SCHED_RATELIMIT_MIN 100
- unsigned ratelimit_us;
-};
-typedef struct xen_sysctl_credit_schedule xen_sysctl_credit_schedule_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_credit_schedule_t);
-
-/* XEN_SYSCTL_scheduler_op */
-/* Set or get info? */
-#define XEN_SYSCTL_SCHEDOP_putinfo 0
-#define XEN_SYSCTL_SCHEDOP_getinfo 1
-struct xen_sysctl_scheduler_op {
- uint32_t cpupool_id; /* Cpupool whose scheduler is to be targetted. */
- uint32_t sched_id; /* XEN_SCHEDULER_* (domctl.h) */
- uint32_t cmd; /* XEN_SYSCTL_SCHEDOP_* */
- union {
- struct xen_sysctl_sched_arinc653 {
- XEN_GUEST_HANDLE_64(xen_sysctl_arinc653_schedule_t) schedule;
- } sched_arinc653;
- struct xen_sysctl_credit_schedule sched_credit;
- } u;
-};
-typedef struct xen_sysctl_scheduler_op xen_sysctl_scheduler_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_scheduler_op_t);
-
-/* XEN_SYSCTL_coverage_op */
-/*
- * Get total size of information, to help allocate
- * the buffer. The pointer points to a 32 bit value.
- */
-#define XEN_SYSCTL_COVERAGE_get_total_size 0
-
-/*
- * Read coverage information in a single run
- * You must use a tool to split them.
- */
-#define XEN_SYSCTL_COVERAGE_read 1
-
-/*
- * Reset all the coverage counters to 0
- * No parameters.
- */
-#define XEN_SYSCTL_COVERAGE_reset 2
-
-/*
- * Like XEN_SYSCTL_COVERAGE_read but reset also
- * counters to 0 in a single call.
- */
-#define XEN_SYSCTL_COVERAGE_read_and_reset 3
-
-struct xen_sysctl_coverage_op {
- uint32_t cmd; /* XEN_SYSCTL_COVERAGE_* */
- union {
- uint32_t total_size; /* OUT */
- XEN_GUEST_HANDLE_64(uint8) raw_info; /* OUT */
- } u;
-};
-typedef struct xen_sysctl_coverage_op xen_sysctl_coverage_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_coverage_op_t);
-
-#define XEN_SYSCTL_PSR_CMT_get_total_rmid 0
-#define XEN_SYSCTL_PSR_CMT_get_l3_upscaling_factor 1
-/* The L3 cache size is returned in KB unit */
-#define XEN_SYSCTL_PSR_CMT_get_l3_cache_size 2
-#define XEN_SYSCTL_PSR_CMT_enabled 3
-#define XEN_SYSCTL_PSR_CMT_get_l3_event_mask 4
-struct xen_sysctl_psr_cmt_op {
- uint32_t cmd; /* IN: XEN_SYSCTL_PSR_CMT_* */
- uint32_t flags; /* padding variable, may be extended for future use */
- union {
- uint64_t data; /* OUT */
- struct {
- uint32_t cpu; /* IN */
- uint32_t rsvd;
- } l3_cache;
- } u;
-};
-typedef struct xen_sysctl_psr_cmt_op xen_sysctl_psr_cmt_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_psr_cmt_op_t);
-
-struct xen_sysctl {
- uint32_t cmd;
-#define XEN_SYSCTL_readconsole 1
-#define XEN_SYSCTL_tbuf_op 2
-#define XEN_SYSCTL_physinfo 3
-#define XEN_SYSCTL_sched_id 4
-#define XEN_SYSCTL_perfc_op 5
-#define XEN_SYSCTL_getdomaininfolist 6
-#define XEN_SYSCTL_debug_keys 7
-#define XEN_SYSCTL_getcpuinfo 8
-#define XEN_SYSCTL_availheap 9
-#define XEN_SYSCTL_get_pmstat 10
-#define XEN_SYSCTL_cpu_hotplug 11
-#define XEN_SYSCTL_pm_op 12
-#define XEN_SYSCTL_page_offline_op 14
-#define XEN_SYSCTL_lockprof_op 15
-#define XEN_SYSCTL_topologyinfo 16
-#define XEN_SYSCTL_numainfo 17
-#define XEN_SYSCTL_cpupool_op 18
-#define XEN_SYSCTL_scheduler_op 19
-#define XEN_SYSCTL_coverage_op 20
-#define XEN_SYSCTL_psr_cmt_op 21
- uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
- union {
- struct xen_sysctl_readconsole readconsole;
- struct xen_sysctl_tbuf_op tbuf_op;
- struct xen_sysctl_physinfo physinfo;
- struct xen_sysctl_topologyinfo topologyinfo;
- struct xen_sysctl_numainfo numainfo;
- struct xen_sysctl_sched_id sched_id;
- struct xen_sysctl_perfc_op perfc_op;
- struct xen_sysctl_getdomaininfolist getdomaininfolist;
- struct xen_sysctl_debug_keys debug_keys;
- struct xen_sysctl_getcpuinfo getcpuinfo;
- struct xen_sysctl_availheap availheap;
- struct xen_sysctl_get_pmstat get_pmstat;
- struct xen_sysctl_cpu_hotplug cpu_hotplug;
- struct xen_sysctl_pm_op pm_op;
- struct xen_sysctl_page_offline_op page_offline;
- struct xen_sysctl_lockprof_op lockprof_op;
- struct xen_sysctl_cpupool_op cpupool_op;
- struct xen_sysctl_scheduler_op scheduler_op;
- struct xen_sysctl_coverage_op coverage_op;
- struct xen_sysctl_psr_cmt_op psr_cmt_op;
- uint8_t pad[128];
- } u;
-};
-typedef struct xen_sysctl xen_sysctl_t;
-DEFINE_XEN_GUEST_HANDLE(xen_sysctl_t);
-
-#endif /* __XEN_PUBLIC_SYSCTL_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * tmem.h
- *
- * Guest OS interface to Xen Transcendent Memory.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2004, K A Fraser
- */
-
-#ifndef __XEN_PUBLIC_TMEM_H__
-#define __XEN_PUBLIC_TMEM_H__
-
-#include "xen.h"
-
-/* version of ABI */
-#define TMEM_SPEC_VERSION 1
-
-/* Commands to HYPERVISOR_tmem_op() */
-#define TMEM_CONTROL 0
-#define TMEM_NEW_POOL 1
-#define TMEM_DESTROY_POOL 2
-#define TMEM_PUT_PAGE 4
-#define TMEM_GET_PAGE 5
-#define TMEM_FLUSH_PAGE 6
-#define TMEM_FLUSH_OBJECT 7
-#if __XEN_INTERFACE_VERSION__ < 0x00040400
-#define TMEM_NEW_PAGE 3
-#define TMEM_READ 8
-#define TMEM_WRITE 9
-#define TMEM_XCHG 10
-#endif
-
-/* Privileged commands to HYPERVISOR_tmem_op() */
-#define TMEM_AUTH 101
-#define TMEM_RESTORE_NEW 102
-
-/* Subops for HYPERVISOR_tmem_op(TMEM_CONTROL) */
-#define TMEMC_THAW 0
-#define TMEMC_FREEZE 1
-#define TMEMC_FLUSH 2
-#define TMEMC_DESTROY 3
-#define TMEMC_LIST 4
-#define TMEMC_SET_WEIGHT 5
-#define TMEMC_SET_CAP 6
-#define TMEMC_SET_COMPRESS 7
-#define TMEMC_QUERY_FREEABLE_MB 8
-#define TMEMC_SAVE_BEGIN 10
-#define TMEMC_SAVE_GET_VERSION 11
-#define TMEMC_SAVE_GET_MAXPOOLS 12
-#define TMEMC_SAVE_GET_CLIENT_WEIGHT 13
-#define TMEMC_SAVE_GET_CLIENT_CAP 14
-#define TMEMC_SAVE_GET_CLIENT_FLAGS 15
-#define TMEMC_SAVE_GET_POOL_FLAGS 16
-#define TMEMC_SAVE_GET_POOL_NPAGES 17
-#define TMEMC_SAVE_GET_POOL_UUID 18
-#define TMEMC_SAVE_GET_NEXT_PAGE 19
-#define TMEMC_SAVE_GET_NEXT_INV 20
-#define TMEMC_SAVE_END 21
-#define TMEMC_RESTORE_BEGIN 30
-#define TMEMC_RESTORE_PUT_PAGE 32
-#define TMEMC_RESTORE_FLUSH_PAGE 33
-
-/* Bits for HYPERVISOR_tmem_op(TMEM_NEW_POOL) */
-#define TMEM_POOL_PERSIST 1
-#define TMEM_POOL_SHARED 2
-#define TMEM_POOL_PRECOMPRESSED 4
-#define TMEM_POOL_PAGESIZE_SHIFT 4
-#define TMEM_POOL_PAGESIZE_MASK 0xf
-#define TMEM_POOL_VERSION_SHIFT 24
-#define TMEM_POOL_VERSION_MASK 0xff
-#define TMEM_POOL_RESERVED_BITS 0x00ffff00
-
-/* Bits for client flags (save/restore) */
-#define TMEM_CLIENT_COMPRESS 1
-#define TMEM_CLIENT_FROZEN 2
-
-/* Special errno values */
-#define EFROZEN 1000
-#define EEMPTY 1001
-
-
-#ifndef __ASSEMBLY__
-#if __XEN_INTERFACE_VERSION__ < 0x00040400
-typedef xen_pfn_t tmem_cli_mfn_t;
-#endif
-typedef XEN_GUEST_HANDLE(char) tmem_cli_va_t;
-struct tmem_op {
- uint32_t cmd;
- int32_t pool_id;
- union {
- struct {
- uint64_t uuid[2];
- uint32_t flags;
- uint32_t arg1;
- } creat; /* for cmd == TMEM_NEW_POOL, TMEM_AUTH, TMEM_RESTORE_NEW */
- struct {
- uint32_t subop;
- uint32_t cli_id;
- uint32_t arg1;
- uint32_t arg2;
- uint64_t oid[3];
- tmem_cli_va_t buf;
- } ctrl; /* for cmd == TMEM_CONTROL */
- struct {
-
- uint64_t oid[3];
- uint32_t index;
- uint32_t tmem_offset;
- uint32_t pfn_offset;
- uint32_t len;
- xen_pfn_t cmfn; /* client machine page frame */
- } gen; /* for all other cmd ("generic") */
- } u;
-};
-typedef struct tmem_op tmem_op_t;
-DEFINE_XEN_GUEST_HANDLE(tmem_op_t);
-
-struct tmem_handle {
- uint32_t pool_id;
- uint32_t index;
- uint64_t oid[3];
-};
-#endif
-
-#endif /* __XEN_PUBLIC_TMEM_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * include/public/trace.h
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Mark Williamson, (C) 2004 Intel Research Cambridge
- * Copyright (C) 2005 Bin Ren
- */
-
-#ifndef __XEN_PUBLIC_TRACE_H__
-#define __XEN_PUBLIC_TRACE_H__
-
-#define TRACE_EXTRA_MAX 7
-#define TRACE_EXTRA_SHIFT 28
-
-/* Trace classes */
-#define TRC_CLS_SHIFT 16
-#define TRC_GEN 0x0001f000 /* General trace */
-#define TRC_SCHED 0x0002f000 /* Xen Scheduler trace */
-#define TRC_DOM0OP 0x0004f000 /* Xen DOM0 operation trace */
-#define TRC_HVM 0x0008f000 /* Xen HVM trace */
-#define TRC_MEM 0x0010f000 /* Xen memory trace */
-#define TRC_PV 0x0020f000 /* Xen PV traces */
-#define TRC_SHADOW 0x0040f000 /* Xen shadow tracing */
-#define TRC_HW 0x0080f000 /* Xen hardware-related traces */
-#define TRC_GUEST 0x0800f000 /* Guest-generated traces */
-#define TRC_ALL 0x0ffff000
-#define TRC_HD_TO_EVENT(x) ((x)&0x0fffffff)
-#define TRC_HD_CYCLE_FLAG (1UL<<31)
-#define TRC_HD_INCLUDES_CYCLE_COUNT(x) ( !!( (x) & TRC_HD_CYCLE_FLAG ) )
-#define TRC_HD_EXTRA(x) (((x)>>TRACE_EXTRA_SHIFT)&TRACE_EXTRA_MAX)
-
-/* Trace subclasses */
-#define TRC_SUBCLS_SHIFT 12
-
-/* trace subclasses for SVM */
-#define TRC_HVM_ENTRYEXIT 0x00081000 /* VMENTRY and #VMEXIT */
-#define TRC_HVM_HANDLER 0x00082000 /* various HVM handlers */
-#define TRC_HVM_EMUL 0x00084000 /* emulated devices */
-
-#define TRC_SCHED_MIN 0x00021000 /* Just runstate changes */
-#define TRC_SCHED_CLASS 0x00022000 /* Scheduler-specific */
-#define TRC_SCHED_VERBOSE 0x00028000 /* More inclusive scheduling */
-
-/*
- * The highest 3 bits of the last 12 bits of TRC_SCHED_CLASS above are
- * reserved for encoding what scheduler produced the information. The
- * actual event is encoded in the last 9 bits.
- *
- * This means we have 8 scheduling IDs available (which means at most 8
- * schedulers generating events) and, in each scheduler, up to 512
- * different events.
- */
-#define TRC_SCHED_ID_BITS 3
-#define TRC_SCHED_ID_SHIFT (TRC_SUBCLS_SHIFT - TRC_SCHED_ID_BITS)
-#define TRC_SCHED_ID_MASK (((1UL<<TRC_SCHED_ID_BITS) - 1) << TRC_SCHED_ID_SHIFT)
-#define TRC_SCHED_EVT_MASK (~(TRC_SCHED_ID_MASK))
-
-/* Per-scheduler IDs, to identify scheduler specific events */
-#define TRC_SCHED_CSCHED 0
-#define TRC_SCHED_CSCHED2 1
-#define TRC_SCHED_SEDF 2
-#define TRC_SCHED_ARINC653 3
-#define TRC_SCHED_RTDS 4
-
-/* Per-scheduler tracing */
-#define TRC_SCHED_CLASS_EVT(_c, _e) \
- ( ( TRC_SCHED_CLASS | \
- ((TRC_SCHED_##_c << TRC_SCHED_ID_SHIFT) & TRC_SCHED_ID_MASK) ) + \
- (_e & TRC_SCHED_EVT_MASK) )
-
-/* Trace classes for Hardware */
-#define TRC_HW_PM 0x00801000 /* Power management traces */
-#define TRC_HW_IRQ 0x00802000 /* Traces relating to the handling of IRQs */
-
-/* Trace events per class */
-#define TRC_LOST_RECORDS (TRC_GEN + 1)
-#define TRC_TRACE_WRAP_BUFFER (TRC_GEN + 2)
-#define TRC_TRACE_CPU_CHANGE (TRC_GEN + 3)
-
-#define TRC_SCHED_RUNSTATE_CHANGE (TRC_SCHED_MIN + 1)
-#define TRC_SCHED_CONTINUE_RUNNING (TRC_SCHED_MIN + 2)
-#define TRC_SCHED_DOM_ADD (TRC_SCHED_VERBOSE + 1)
-#define TRC_SCHED_DOM_REM (TRC_SCHED_VERBOSE + 2)
-#define TRC_SCHED_SLEEP (TRC_SCHED_VERBOSE + 3)
-#define TRC_SCHED_WAKE (TRC_SCHED_VERBOSE + 4)
-#define TRC_SCHED_YIELD (TRC_SCHED_VERBOSE + 5)
-#define TRC_SCHED_BLOCK (TRC_SCHED_VERBOSE + 6)
-#define TRC_SCHED_SHUTDOWN (TRC_SCHED_VERBOSE + 7)
-#define TRC_SCHED_CTL (TRC_SCHED_VERBOSE + 8)
-#define TRC_SCHED_ADJDOM (TRC_SCHED_VERBOSE + 9)
-#define TRC_SCHED_SWITCH (TRC_SCHED_VERBOSE + 10)
-#define TRC_SCHED_S_TIMER_FN (TRC_SCHED_VERBOSE + 11)
-#define TRC_SCHED_T_TIMER_FN (TRC_SCHED_VERBOSE + 12)
-#define TRC_SCHED_DOM_TIMER_FN (TRC_SCHED_VERBOSE + 13)
-#define TRC_SCHED_SWITCH_INFPREV (TRC_SCHED_VERBOSE + 14)
-#define TRC_SCHED_SWITCH_INFNEXT (TRC_SCHED_VERBOSE + 15)
-#define TRC_SCHED_SHUTDOWN_CODE (TRC_SCHED_VERBOSE + 16)
-
-#define TRC_MEM_PAGE_GRANT_MAP (TRC_MEM + 1)
-#define TRC_MEM_PAGE_GRANT_UNMAP (TRC_MEM + 2)
-#define TRC_MEM_PAGE_GRANT_TRANSFER (TRC_MEM + 3)
-#define TRC_MEM_SET_P2M_ENTRY (TRC_MEM + 4)
-#define TRC_MEM_DECREASE_RESERVATION (TRC_MEM + 5)
-#define TRC_MEM_POD_POPULATE (TRC_MEM + 16)
-#define TRC_MEM_POD_ZERO_RECLAIM (TRC_MEM + 17)
-#define TRC_MEM_POD_SUPERPAGE_SPLINTER (TRC_MEM + 18)
-
-#define TRC_PV_ENTRY 0x00201000 /* Hypervisor entry points for PV guests. */
-#define TRC_PV_SUBCALL 0x00202000 /* Sub-call in a multicall hypercall */
-
-#define TRC_PV_HYPERCALL (TRC_PV_ENTRY + 1)
-#define TRC_PV_TRAP (TRC_PV_ENTRY + 3)
-#define TRC_PV_PAGE_FAULT (TRC_PV_ENTRY + 4)
-#define TRC_PV_FORCED_INVALID_OP (TRC_PV_ENTRY + 5)
-#define TRC_PV_EMULATE_PRIVOP (TRC_PV_ENTRY + 6)
-#define TRC_PV_EMULATE_4GB (TRC_PV_ENTRY + 7)
-#define TRC_PV_MATH_STATE_RESTORE (TRC_PV_ENTRY + 8)
-#define TRC_PV_PAGING_FIXUP (TRC_PV_ENTRY + 9)
-#define TRC_PV_GDT_LDT_MAPPING_FAULT (TRC_PV_ENTRY + 10)
-#define TRC_PV_PTWR_EMULATION (TRC_PV_ENTRY + 11)
-#define TRC_PV_PTWR_EMULATION_PAE (TRC_PV_ENTRY + 12)
-#define TRC_PV_HYPERCALL_V2 (TRC_PV_ENTRY + 13)
-#define TRC_PV_HYPERCALL_SUBCALL (TRC_PV_SUBCALL + 14)
-
-/*
- * TRC_PV_HYPERCALL_V2 format
- *
- * Only some of the hypercall argument are recorded. Bit fields A0 to
- * A5 in the first extra word are set if the argument is present and
- * the arguments themselves are packed sequentially in the following
- * words.
- *
- * The TRC_64_FLAG bit is not set for these events (even if there are
- * 64-bit arguments in the record).
- *
- * Word
- * 0 bit 31 30|29 28|27 26|25 24|23 22|21 20|19 ... 0
- * A5 |A4 |A3 |A2 |A1 |A0 |Hypercall op
- * 1 First 32 bit (or low word of first 64 bit) arg in record
- * 2 Second 32 bit (or high word of first 64 bit) arg in record
- * ...
- *
- * A0-A5 bitfield values:
- *
- * 00b Argument not present
- * 01b 32-bit argument present
- * 10b 64-bit argument present
- * 11b Reserved
- */
-#define TRC_PV_HYPERCALL_V2_ARG_32(i) (0x1 << (20 + 2*(i)))
-#define TRC_PV_HYPERCALL_V2_ARG_64(i) (0x2 << (20 + 2*(i)))
-#define TRC_PV_HYPERCALL_V2_ARG_MASK (0xfff00000)
-
-#define TRC_SHADOW_NOT_SHADOW (TRC_SHADOW + 1)
-#define TRC_SHADOW_FAST_PROPAGATE (TRC_SHADOW + 2)
-#define TRC_SHADOW_FAST_MMIO (TRC_SHADOW + 3)
-#define TRC_SHADOW_FALSE_FAST_PATH (TRC_SHADOW + 4)
-#define TRC_SHADOW_MMIO (TRC_SHADOW + 5)
-#define TRC_SHADOW_FIXUP (TRC_SHADOW + 6)
-#define TRC_SHADOW_DOMF_DYING (TRC_SHADOW + 7)
-#define TRC_SHADOW_EMULATE (TRC_SHADOW + 8)
-#define TRC_SHADOW_EMULATE_UNSHADOW_USER (TRC_SHADOW + 9)
-#define TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ (TRC_SHADOW + 10)
-#define TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED (TRC_SHADOW + 11)
-#define TRC_SHADOW_WRMAP_BF (TRC_SHADOW + 12)
-#define TRC_SHADOW_PREALLOC_UNPIN (TRC_SHADOW + 13)
-#define TRC_SHADOW_RESYNC_FULL (TRC_SHADOW + 14)
-#define TRC_SHADOW_RESYNC_ONLY (TRC_SHADOW + 15)
-
-/* trace events per subclass */
-#define TRC_HVM_NESTEDFLAG (0x400)
-#define TRC_HVM_VMENTRY (TRC_HVM_ENTRYEXIT + 0x01)
-#define TRC_HVM_VMEXIT (TRC_HVM_ENTRYEXIT + 0x02)
-#define TRC_HVM_VMEXIT64 (TRC_HVM_ENTRYEXIT + TRC_64_FLAG + 0x02)
-#define TRC_HVM_PF_XEN (TRC_HVM_HANDLER + 0x01)
-#define TRC_HVM_PF_XEN64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x01)
-#define TRC_HVM_PF_INJECT (TRC_HVM_HANDLER + 0x02)
-#define TRC_HVM_PF_INJECT64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x02)
-#define TRC_HVM_INJ_EXC (TRC_HVM_HANDLER + 0x03)
-#define TRC_HVM_INJ_VIRQ (TRC_HVM_HANDLER + 0x04)
-#define TRC_HVM_REINJ_VIRQ (TRC_HVM_HANDLER + 0x05)
-#define TRC_HVM_IO_READ (TRC_HVM_HANDLER + 0x06)
-#define TRC_HVM_IO_WRITE (TRC_HVM_HANDLER + 0x07)
-#define TRC_HVM_CR_READ (TRC_HVM_HANDLER + 0x08)
-#define TRC_HVM_CR_READ64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x08)
-#define TRC_HVM_CR_WRITE (TRC_HVM_HANDLER + 0x09)
-#define TRC_HVM_CR_WRITE64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x09)
-#define TRC_HVM_DR_READ (TRC_HVM_HANDLER + 0x0A)
-#define TRC_HVM_DR_WRITE (TRC_HVM_HANDLER + 0x0B)
-#define TRC_HVM_MSR_READ (TRC_HVM_HANDLER + 0x0C)
-#define TRC_HVM_MSR_WRITE (TRC_HVM_HANDLER + 0x0D)
-#define TRC_HVM_CPUID (TRC_HVM_HANDLER + 0x0E)
-#define TRC_HVM_INTR (TRC_HVM_HANDLER + 0x0F)
-#define TRC_HVM_NMI (TRC_HVM_HANDLER + 0x10)
-#define TRC_HVM_SMI (TRC_HVM_HANDLER + 0x11)
-#define TRC_HVM_VMMCALL (TRC_HVM_HANDLER + 0x12)
-#define TRC_HVM_HLT (TRC_HVM_HANDLER + 0x13)
-#define TRC_HVM_INVLPG (TRC_HVM_HANDLER + 0x14)
-#define TRC_HVM_INVLPG64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x14)
-#define TRC_HVM_MCE (TRC_HVM_HANDLER + 0x15)
-#define TRC_HVM_IOPORT_READ (TRC_HVM_HANDLER + 0x16)
-#define TRC_HVM_IOMEM_READ (TRC_HVM_HANDLER + 0x17)
-#define TRC_HVM_CLTS (TRC_HVM_HANDLER + 0x18)
-#define TRC_HVM_LMSW (TRC_HVM_HANDLER + 0x19)
-#define TRC_HVM_LMSW64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x19)
-#define TRC_HVM_RDTSC (TRC_HVM_HANDLER + 0x1a)
-#define TRC_HVM_INTR_WINDOW (TRC_HVM_HANDLER + 0x20)
-#define TRC_HVM_NPF (TRC_HVM_HANDLER + 0x21)
-#define TRC_HVM_REALMODE_EMULATE (TRC_HVM_HANDLER + 0x22)
-#define TRC_HVM_TRAP (TRC_HVM_HANDLER + 0x23)
-#define TRC_HVM_TRAP_DEBUG (TRC_HVM_HANDLER + 0x24)
-#define TRC_HVM_VLAPIC (TRC_HVM_HANDLER + 0x25)
-
-#define TRC_HVM_IOPORT_WRITE (TRC_HVM_HANDLER + 0x216)
-#define TRC_HVM_IOMEM_WRITE (TRC_HVM_HANDLER + 0x217)
-
-/* Trace events for emulated devices */
-#define TRC_HVM_EMUL_HPET_START_TIMER (TRC_HVM_EMUL + 0x1)
-#define TRC_HVM_EMUL_PIT_START_TIMER (TRC_HVM_EMUL + 0x2)
-#define TRC_HVM_EMUL_RTC_START_TIMER (TRC_HVM_EMUL + 0x3)
-#define TRC_HVM_EMUL_LAPIC_START_TIMER (TRC_HVM_EMUL + 0x4)
-#define TRC_HVM_EMUL_HPET_STOP_TIMER (TRC_HVM_EMUL + 0x5)
-#define TRC_HVM_EMUL_PIT_STOP_TIMER (TRC_HVM_EMUL + 0x6)
-#define TRC_HVM_EMUL_RTC_STOP_TIMER (TRC_HVM_EMUL + 0x7)
-#define TRC_HVM_EMUL_LAPIC_STOP_TIMER (TRC_HVM_EMUL + 0x8)
-#define TRC_HVM_EMUL_PIT_TIMER_CB (TRC_HVM_EMUL + 0x9)
-#define TRC_HVM_EMUL_LAPIC_TIMER_CB (TRC_HVM_EMUL + 0xA)
-#define TRC_HVM_EMUL_PIC_INT_OUTPUT (TRC_HVM_EMUL + 0xB)
-#define TRC_HVM_EMUL_PIC_KICK (TRC_HVM_EMUL + 0xC)
-#define TRC_HVM_EMUL_PIC_INTACK (TRC_HVM_EMUL + 0xD)
-#define TRC_HVM_EMUL_PIC_POSEDGE (TRC_HVM_EMUL + 0xE)
-#define TRC_HVM_EMUL_PIC_NEGEDGE (TRC_HVM_EMUL + 0xF)
-#define TRC_HVM_EMUL_PIC_PEND_IRQ_CALL (TRC_HVM_EMUL + 0x10)
-#define TRC_HVM_EMUL_LAPIC_PIC_INTR (TRC_HVM_EMUL + 0x11)
-
-/* trace events for per class */
-#define TRC_PM_FREQ_CHANGE (TRC_HW_PM + 0x01)
-#define TRC_PM_IDLE_ENTRY (TRC_HW_PM + 0x02)
-#define TRC_PM_IDLE_EXIT (TRC_HW_PM + 0x03)
-
-/* Trace events for IRQs */
-#define TRC_HW_IRQ_MOVE_CLEANUP_DELAY (TRC_HW_IRQ + 0x1)
-#define TRC_HW_IRQ_MOVE_CLEANUP (TRC_HW_IRQ + 0x2)
-#define TRC_HW_IRQ_BIND_VECTOR (TRC_HW_IRQ + 0x3)
-#define TRC_HW_IRQ_CLEAR_VECTOR (TRC_HW_IRQ + 0x4)
-#define TRC_HW_IRQ_MOVE_FINISH (TRC_HW_IRQ + 0x5)
-#define TRC_HW_IRQ_ASSIGN_VECTOR (TRC_HW_IRQ + 0x6)
-#define TRC_HW_IRQ_UNMAPPED_VECTOR (TRC_HW_IRQ + 0x7)
-#define TRC_HW_IRQ_HANDLED (TRC_HW_IRQ + 0x8)
-
-/*
- * Event Flags
- *
- * Some events (e.g, TRC_PV_TRAP and TRC_HVM_IOMEM_READ) have multiple
- * record formats. These event flags distinguish between the
- * different formats.
- */
-#define TRC_64_FLAG 0x100 /* Addresses are 64 bits (instead of 32 bits) */
-
-/* This structure represents a single trace buffer record. */
-struct t_rec {
- uint32_t event:28;
- uint32_t extra_u32:3; /* # entries in trailing extra_u32[] array */
- uint32_t cycles_included:1; /* u.cycles or u.no_cycles? */
- union {
- struct {
- uint32_t cycles_lo, cycles_hi; /* cycle counter timestamp */
- uint32_t extra_u32[7]; /* event data items */
- } cycles;
- struct {
- uint32_t extra_u32[7]; /* event data items */
- } nocycles;
- } u;
-};
-
-/*
- * This structure contains the metadata for a single trace buffer. The head
- * field, indexes into an array of struct t_rec's.
- */
-struct t_buf {
- /* Assume the data buffer size is X. X is generally not a power of 2.
- * CONS and PROD are incremented modulo (2*X):
- * 0 <= cons < 2*X
- * 0 <= prod < 2*X
- * This is done because addition modulo X breaks at 2^32 when X is not a
- * power of 2:
- * (((2^32 - 1) % X) + 1) % X != (2^32) % X
- */
- uint32_t cons; /* Offset of next item to be consumed by control tools. */
- uint32_t prod; /* Offset of next item to be produced by Xen. */
- /* Records follow immediately after the meta-data header. */
-};
-
-/* Structure used to pass MFNs to the trace buffers back to trace consumers.
- * Offset is an offset into the mapped structure where the mfn list will be held.
- * MFNs will be at ((unsigned long *)(t_info))+(t_info->cpu_offset[cpu]).
- */
-struct t_info {
- uint16_t tbuf_size; /* Size in pages of each trace buffer */
- uint16_t mfn_offset[]; /* Offset within t_info structure of the page list per cpu */
- /* MFN lists immediately after the header */
-};
-
-#endif /* __XEN_PUBLIC_TRACE_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * vcpu.h
- *
- * VCPU initialisation, query, and hotplug.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
- */
-
-#ifndef __XEN_PUBLIC_VCPU_H__
-#define __XEN_PUBLIC_VCPU_H__
-
-#include "xen.h"
-
-/*
- * Prototype for this hypercall is:
- * long vcpu_op(int cmd, unsigned int vcpuid, void *extra_args)
- * @cmd == VCPUOP_??? (VCPU operation).
- * @vcpuid == VCPU to operate on.
- * @extra_args == Operation-specific extra arguments (NULL if none).
- */
-
-/*
- * Initialise a VCPU. Each VCPU can be initialised only once. A
- * newly-initialised VCPU will not run until it is brought up by VCPUOP_up.
- *
- * @extra_arg == pointer to vcpu_guest_context structure containing initial
- * state for the VCPU.
- */
-#define VCPUOP_initialise 0
-
-/*
- * Bring up a VCPU. This makes the VCPU runnable. This operation will fail
- * if the VCPU has not been initialised (VCPUOP_initialise).
- */
-#define VCPUOP_up 1
-
-/*
- * Bring down a VCPU (i.e., make it non-runnable).
- * There are a few caveats that callers should observe:
- * 1. This operation may return, and VCPU_is_up may return false, before the
- * VCPU stops running (i.e., the command is asynchronous). It is a good
- * idea to ensure that the VCPU has entered a non-critical loop before
- * bringing it down. Alternatively, this operation is guaranteed
- * synchronous if invoked by the VCPU itself.
- * 2. After a VCPU is initialised, there is currently no way to drop all its
- * references to domain memory. Even a VCPU that is down still holds
- * memory references via its pagetable base pointer and GDT. It is good
- * practise to move a VCPU onto an 'idle' or default page table, LDT and
- * GDT before bringing it down.
- */
-#define VCPUOP_down 2
-
-/* Returns 1 if the given VCPU is up. */
-#define VCPUOP_is_up 3
-
-/*
- * Return information about the state and running time of a VCPU.
- * @extra_arg == pointer to vcpu_runstate_info structure.
- */
-#define VCPUOP_get_runstate_info 4
-struct vcpu_runstate_info {
- /* VCPU's current state (RUNSTATE_*). */
- int state;
- /* When was current state entered (system time, ns)? */
- uint64_t state_entry_time;
- /*
- * Time spent in each RUNSTATE_* (ns). The sum of these times is
- * guaranteed not to drift from system time.
- */
- uint64_t time[4];
-};
-typedef struct vcpu_runstate_info vcpu_runstate_info_t;
-DEFINE_XEN_GUEST_HANDLE(vcpu_runstate_info_t);
-
-/* VCPU is currently running on a physical CPU. */
-#define RUNSTATE_running 0
-
-/* VCPU is runnable, but not currently scheduled on any physical CPU. */
-#define RUNSTATE_runnable 1
-
-/* VCPU is blocked (a.k.a. idle). It is therefore not runnable. */
-#define RUNSTATE_blocked 2
-
-/*
- * VCPU is not runnable, but it is not blocked.
- * This is a 'catch all' state for things like hotplug and pauses by the
- * system administrator (or for critical sections in the hypervisor).
- * RUNSTATE_blocked dominates this state (it is the preferred state).
- */
-#define RUNSTATE_offline 3
-
-/*
- * Register a shared memory area from which the guest may obtain its own
- * runstate information without needing to execute a hypercall.
- * Notes:
- * 1. The registered address may be virtual or physical or guest handle,
- * depending on the platform. Virtual address or guest handle should be
- * registered on x86 systems.
- * 2. Only one shared area may be registered per VCPU. The shared area is
- * updated by the hypervisor each time the VCPU is scheduled. Thus
- * runstate.state will always be RUNSTATE_running and
- * runstate.state_entry_time will indicate the system time at which the
- * VCPU was last scheduled to run.
- * @extra_arg == pointer to vcpu_register_runstate_memory_area structure.
- */
-#define VCPUOP_register_runstate_memory_area 5
-struct vcpu_register_runstate_memory_area {
- union {
- XEN_GUEST_HANDLE(vcpu_runstate_info_t) h;
- struct vcpu_runstate_info *v;
- uint64_t p;
- } addr;
-};
-typedef struct vcpu_register_runstate_memory_area vcpu_register_runstate_memory_area_t;
-DEFINE_XEN_GUEST_HANDLE(vcpu_register_runstate_memory_area_t);
-
-/*
- * Set or stop a VCPU's periodic timer. Every VCPU has one periodic timer
- * which can be set via these commands. Periods smaller than one millisecond
- * may not be supported.
- */
-#define VCPUOP_set_periodic_timer 6 /* arg == vcpu_set_periodic_timer_t */
-#define VCPUOP_stop_periodic_timer 7 /* arg == NULL */
-struct vcpu_set_periodic_timer {
- uint64_t period_ns;
-};
-typedef struct vcpu_set_periodic_timer vcpu_set_periodic_timer_t;
-DEFINE_XEN_GUEST_HANDLE(vcpu_set_periodic_timer_t);
-
-/*
- * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot
- * timer which can be set via these commands.
- */
-#define VCPUOP_set_singleshot_timer 8 /* arg == vcpu_set_singleshot_timer_t */
-#define VCPUOP_stop_singleshot_timer 9 /* arg == NULL */
-struct vcpu_set_singleshot_timer {
- uint64_t timeout_abs_ns; /* Absolute system time value in nanoseconds. */
- uint32_t flags; /* VCPU_SSHOTTMR_??? */
-};
-typedef struct vcpu_set_singleshot_timer vcpu_set_singleshot_timer_t;
-DEFINE_XEN_GUEST_HANDLE(vcpu_set_singleshot_timer_t);
-
-/* Flags to VCPUOP_set_singleshot_timer. */
- /* Require the timeout to be in the future (return -ETIME if it's passed). */
-#define _VCPU_SSHOTTMR_future (0)
-#define VCPU_SSHOTTMR_future (1U << _VCPU_SSHOTTMR_future)
-
-/*
- * Register a memory location in the guest address space for the
- * vcpu_info structure. This allows the guest to place the vcpu_info
- * structure in a convenient place, such as in a per-cpu data area.
- * The pointer need not be page aligned, but the structure must not
- * cross a page boundary.
- *
- * This may be called only once per vcpu.
- */
-#define VCPUOP_register_vcpu_info 10 /* arg == vcpu_register_vcpu_info_t */
-struct vcpu_register_vcpu_info {
- uint64_t mfn; /* mfn of page to place vcpu_info */
- uint32_t offset; /* offset within page */
- uint32_t rsvd; /* unused */
-};
-typedef struct vcpu_register_vcpu_info vcpu_register_vcpu_info_t;
-DEFINE_XEN_GUEST_HANDLE(vcpu_register_vcpu_info_t);
-
-/* Send an NMI to the specified VCPU. @extra_arg == NULL. */
-#define VCPUOP_send_nmi 11
-
-/*
- * Get the physical ID information for a pinned vcpu's underlying physical
- * processor. The physical ID informmation is architecture-specific.
- * On x86: id[31:0]=apic_id, id[63:32]=acpi_id.
- * This command returns -EINVAL if it is not a valid operation for this VCPU.
- */
-#define VCPUOP_get_physid 12 /* arg == vcpu_get_physid_t */
-struct vcpu_get_physid {
- uint64_t phys_id;
-};
-typedef struct vcpu_get_physid vcpu_get_physid_t;
-DEFINE_XEN_GUEST_HANDLE(vcpu_get_physid_t);
-#define xen_vcpu_physid_to_x86_apicid(physid) ((uint32_t)(physid))
-#define xen_vcpu_physid_to_x86_acpiid(physid) ((uint32_t)((physid) >> 32))
-
-/*
- * Register a memory location to get a secondary copy of the vcpu time
- * parameters. The master copy still exists as part of the vcpu shared
- * memory area, and this secondary copy is updated whenever the master copy
- * is updated (and using the same versioning scheme for synchronisation).
- *
- * The intent is that this copy may be mapped (RO) into userspace so
- * that usermode can compute system time using the time info and the
- * tsc. Usermode will see an array of vcpu_time_info structures, one
- * for each vcpu, and choose the right one by an existing mechanism
- * which allows it to get the current vcpu number (such as via a
- * segment limit). It can then apply the normal algorithm to compute
- * system time from the tsc.
- *
- * @extra_arg == pointer to vcpu_register_time_info_memory_area structure.
- */
-#define VCPUOP_register_vcpu_time_memory_area 13
-DEFINE_XEN_GUEST_HANDLE(vcpu_time_info_t);
-struct vcpu_register_time_memory_area {
- union {
- XEN_GUEST_HANDLE(vcpu_time_info_t) h;
- struct vcpu_time_info *v;
- uint64_t p;
- } addr;
-};
-typedef struct vcpu_register_time_memory_area vcpu_register_time_memory_area_t;
-DEFINE_XEN_GUEST_HANDLE(vcpu_register_time_memory_area_t);
-
-#endif /* __XEN_PUBLIC_VCPU_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * version.h
- *
- * Xen version, type, and compile information.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2005, Nguyen Anh Quynh <aquynh@gmail.com>
- * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
- */
-
-#ifndef __XEN_PUBLIC_VERSION_H__
-#define __XEN_PUBLIC_VERSION_H__
-
-#include "xen.h"
-
-/* NB. All ops return zero on success, except XENVER_{version,pagesize} */
-
-/* arg == NULL; returns major:minor (16:16). */
-#define XENVER_version 0
-
-/* arg == xen_extraversion_t. */
-#define XENVER_extraversion 1
-typedef char xen_extraversion_t[16];
-#define XEN_EXTRAVERSION_LEN (sizeof(xen_extraversion_t))
-
-/* arg == xen_compile_info_t. */
-#define XENVER_compile_info 2
-struct xen_compile_info {
- char compiler[64];
- char compile_by[16];
- char compile_domain[32];
- char compile_date[32];
-};
-typedef struct xen_compile_info xen_compile_info_t;
-
-#define XENVER_capabilities 3
-typedef char xen_capabilities_info_t[1024];
-#define XEN_CAPABILITIES_INFO_LEN (sizeof(xen_capabilities_info_t))
-
-#define XENVER_changeset 4
-typedef char xen_changeset_info_t[64];
-#define XEN_CHANGESET_INFO_LEN (sizeof(xen_changeset_info_t))
-
-#define XENVER_platform_parameters 5
-struct xen_platform_parameters {
- xen_ulong_t virt_start;
-};
-typedef struct xen_platform_parameters xen_platform_parameters_t;
-
-#define XENVER_get_features 6
-struct xen_feature_info {
- unsigned int submap_idx; /* IN: which 32-bit submap to return */
- uint32_t submap; /* OUT: 32-bit submap */
-};
-typedef struct xen_feature_info xen_feature_info_t;
-
-/* Declares the features reported by XENVER_get_features. */
-#include "features.h"
-
-/* arg == NULL; returns host memory page size. */
-#define XENVER_pagesize 7
-
-/* arg == xen_domain_handle_t. */
-#define XENVER_guest_handle 8
-
-#define XENVER_commandline 9
-typedef char xen_commandline_t[1024];
-
-#endif /* __XEN_PUBLIC_VERSION_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * xen-compat.h
- *
- * Guest OS interface to Xen. Compatibility layer.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2006, Christian Limpach
- */
-
-#ifndef __XEN_PUBLIC_XEN_COMPAT_H__
-#define __XEN_PUBLIC_XEN_COMPAT_H__
-
-#define __XEN_LATEST_INTERFACE_VERSION__ 0x00040600
-
-#if defined(__XEN__) || defined(__XEN_TOOLS__)
-/* Xen is built with matching headers and implements the latest interface. */
-#define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__
-#elif !defined(__XEN_INTERFACE_VERSION__)
-/* Guests which do not specify a version get the legacy interface. */
-#define __XEN_INTERFACE_VERSION__ 0x00000000
-#endif
-
-#if __XEN_INTERFACE_VERSION__ > __XEN_LATEST_INTERFACE_VERSION__
-#error "These header files do not support the requested interface version."
-#endif
-
-#endif /* __XEN_PUBLIC_XEN_COMPAT_H__ */
+++ /dev/null
-/******************************************************************************
- * xen.h
- *
- * Guest OS interface to Xen.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (c) 2004, K A Fraser
- */
-
-#ifndef __XEN_PUBLIC_XEN_H__
-#define __XEN_PUBLIC_XEN_H__
-
-#include "xen-compat.h"
-
-#if defined(__i386__) || defined(__x86_64__)
-#include "arch-x86/xen.h"
-#elif defined(__arm__) || defined (__aarch64__)
-#include "arch-arm.h"
-#else
-#error "Unsupported architecture"
-#endif
-
-#ifndef __ASSEMBLY__
-/* Guest handles for primitive C types. */
-DEFINE_XEN_GUEST_HANDLE(char);
-__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
-DEFINE_XEN_GUEST_HANDLE(int);
-__DEFINE_XEN_GUEST_HANDLE(uint, unsigned int);
-#if __XEN_INTERFACE_VERSION__ < 0x00040300
-DEFINE_XEN_GUEST_HANDLE(long);
-__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
-#endif
-DEFINE_XEN_GUEST_HANDLE(void);
-
-DEFINE_XEN_GUEST_HANDLE(uint64_t);
-DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
-DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
-#endif
-
-/*
- * HYPERCALLS
- */
-
-/* `incontents 100 hcalls List of hypercalls
- * ` enum hypercall_num { // __HYPERVISOR_* => HYPERVISOR_*()
- */
-
-#define __HYPERVISOR_set_trap_table 0
-#define __HYPERVISOR_mmu_update 1
-#define __HYPERVISOR_set_gdt 2
-#define __HYPERVISOR_stack_switch 3
-#define __HYPERVISOR_set_callbacks 4
-#define __HYPERVISOR_fpu_taskswitch 5
-#define __HYPERVISOR_sched_op_compat 6 /* compat since 0x00030101 */
-#define __HYPERVISOR_platform_op 7
-#define __HYPERVISOR_set_debugreg 8
-#define __HYPERVISOR_get_debugreg 9
-#define __HYPERVISOR_update_descriptor 10
-#define __HYPERVISOR_memory_op 12
-#define __HYPERVISOR_multicall 13
-#define __HYPERVISOR_update_va_mapping 14
-#define __HYPERVISOR_set_timer_op 15
-#define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */
-#define __HYPERVISOR_xen_version 17
-#define __HYPERVISOR_console_io 18
-#define __HYPERVISOR_physdev_op_compat 19 /* compat since 0x00030202 */
-#define __HYPERVISOR_grant_table_op 20
-#define __HYPERVISOR_vm_assist 21
-#define __HYPERVISOR_update_va_mapping_otherdomain 22
-#define __HYPERVISOR_iret 23 /* x86 only */
-#define __HYPERVISOR_vcpu_op 24
-#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */
-#define __HYPERVISOR_mmuext_op 26
-#define __HYPERVISOR_xsm_op 27
-#define __HYPERVISOR_nmi_op 28
-#define __HYPERVISOR_sched_op 29
-#define __HYPERVISOR_callback_op 30
-#define __HYPERVISOR_xenoprof_op 31
-#define __HYPERVISOR_event_channel_op 32
-#define __HYPERVISOR_physdev_op 33
-#define __HYPERVISOR_hvm_op 34
-#define __HYPERVISOR_sysctl 35
-#define __HYPERVISOR_domctl 36
-#define __HYPERVISOR_kexec_op 37
-#define __HYPERVISOR_tmem_op 38
-#define __HYPERVISOR_xc_reserved_op 39 /* reserved for XenClient */
-
-/* Architecture-specific hypercall definitions. */
-#define __HYPERVISOR_arch_0 48
-#define __HYPERVISOR_arch_1 49
-#define __HYPERVISOR_arch_2 50
-#define __HYPERVISOR_arch_3 51
-#define __HYPERVISOR_arch_4 52
-#define __HYPERVISOR_arch_5 53
-#define __HYPERVISOR_arch_6 54
-#define __HYPERVISOR_arch_7 55
-
-/* ` } */
-
-/*
- * HYPERCALL COMPATIBILITY.
- */
-
-/* New sched_op hypercall introduced in 0x00030101. */
-#if __XEN_INTERFACE_VERSION__ < 0x00030101
-#undef __HYPERVISOR_sched_op
-#define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat
-#endif
-
-/* New event-channel and physdev hypercalls introduced in 0x00030202. */
-#if __XEN_INTERFACE_VERSION__ < 0x00030202
-#undef __HYPERVISOR_event_channel_op
-#define __HYPERVISOR_event_channel_op __HYPERVISOR_event_channel_op_compat
-#undef __HYPERVISOR_physdev_op
-#define __HYPERVISOR_physdev_op __HYPERVISOR_physdev_op_compat
-#endif
-
-/* New platform_op hypercall introduced in 0x00030204. */
-#if __XEN_INTERFACE_VERSION__ < 0x00030204
-#define __HYPERVISOR_dom0_op __HYPERVISOR_platform_op
-#endif
-
-/*
- * VIRTUAL INTERRUPTS
- *
- * Virtual interrupts that a guest OS may receive from Xen.
- *
- * In the side comments, 'V.' denotes a per-VCPU VIRQ while 'G.' denotes a
- * global VIRQ. The former can be bound once per VCPU and cannot be re-bound.
- * The latter can be allocated only once per guest: they must initially be
- * allocated to VCPU0 but can subsequently be re-bound.
- */
-/* ` enum virq { */
-#define VIRQ_TIMER 0 /* V. Timebase update, and/or requested timeout. */
-#define VIRQ_DEBUG 1 /* V. Request guest to dump debug info. */
-#define VIRQ_CONSOLE 2 /* G. (DOM0) Bytes received on emergency console. */
-#define VIRQ_DOM_EXC 3 /* G. (DOM0) Exceptional event for some domain. */
-#define VIRQ_TBUF 4 /* G. (DOM0) Trace buffer has records available. */
-#define VIRQ_DEBUGGER 6 /* G. (DOM0) A domain has paused for debugging. */
-#define VIRQ_XENOPROF 7 /* V. XenOprofile interrupt: new sample available */
-#define VIRQ_CON_RING 8 /* G. (DOM0) Bytes received on console */
-#define VIRQ_PCPU_STATE 9 /* G. (DOM0) PCPU state changed */
-#define VIRQ_MEM_EVENT 10 /* G. (DOM0) A memory event has occured */
-#define VIRQ_XC_RESERVED 11 /* G. Reserved for XenClient */
-#define VIRQ_ENOMEM 12 /* G. (DOM0) Low on heap memory */
-
-/* Architecture-specific VIRQ definitions. */
-#define VIRQ_ARCH_0 16
-#define VIRQ_ARCH_1 17
-#define VIRQ_ARCH_2 18
-#define VIRQ_ARCH_3 19
-#define VIRQ_ARCH_4 20
-#define VIRQ_ARCH_5 21
-#define VIRQ_ARCH_6 22
-#define VIRQ_ARCH_7 23
-/* ` } */
-
-#define NR_VIRQS 24
-
-/*
- * ` enum neg_errnoval
- * ` HYPERVISOR_mmu_update(const struct mmu_update reqs[],
- * ` unsigned count, unsigned *done_out,
- * ` unsigned foreigndom)
- * `
- * @reqs is an array of mmu_update_t structures ((ptr, val) pairs).
- * @count is the length of the above array.
- * @pdone is an output parameter indicating number of completed operations
- * @foreigndom[15:0]: FD, the expected owner of data pages referenced in this
- * hypercall invocation. Can be DOMID_SELF.
- * @foreigndom[31:16]: PFD, the expected owner of pagetable pages referenced
- * in this hypercall invocation. The value of this field
- * (x) encodes the PFD as follows:
- * x == 0 => PFD == DOMID_SELF
- * x != 0 => PFD == x - 1
- *
- * Sub-commands: ptr[1:0] specifies the appropriate MMU_* command.
- * -------------
- * ptr[1:0] == MMU_NORMAL_PT_UPDATE:
- * Updates an entry in a page table belonging to PFD. If updating an L1 table,
- * and the new table entry is valid/present, the mapped frame must belong to
- * FD. If attempting to map an I/O page then the caller assumes the privilege
- * of the FD.
- * FD == DOMID_IO: Permit /only/ I/O mappings, at the priv level of the caller.
- * FD == DOMID_XEN: Map restricted areas of Xen's heap space.
- * ptr[:2] -- Machine address of the page-table entry to modify.
- * val -- Value to write.
- *
- * There also certain implicit requirements when using this hypercall. The
- * pages that make up a pagetable must be mapped read-only in the guest.
- * This prevents uncontrolled guest updates to the pagetable. Xen strictly
- * enforces this, and will disallow any pagetable update which will end up
- * mapping pagetable page RW, and will disallow using any writable page as a
- * pagetable. In practice it means that when constructing a page table for a
- * process, thread, etc, we MUST be very dilligient in following these rules:
- * 1). Start with top-level page (PGD or in Xen language: L4). Fill out
- * the entries.
- * 2). Keep on going, filling out the upper (PUD or L3), and middle (PMD
- * or L2).
- * 3). Start filling out the PTE table (L1) with the PTE entries. Once
- * done, make sure to set each of those entries to RO (so writeable bit
- * is unset). Once that has been completed, set the PMD (L2) for this
- * PTE table as RO.
- * 4). When completed with all of the PMD (L2) entries, and all of them have
- * been set to RO, make sure to set RO the PUD (L3). Do the same
- * operation on PGD (L4) pagetable entries that have a PUD (L3) entry.
- * 5). Now before you can use those pages (so setting the cr3), you MUST also
- * pin them so that the hypervisor can verify the entries. This is done
- * via the HYPERVISOR_mmuext_op(MMUEXT_PIN_L4_TABLE, guest physical frame
- * number of the PGD (L4)). And this point the HYPERVISOR_mmuext_op(
- * MMUEXT_NEW_BASEPTR, guest physical frame number of the PGD (L4)) can be
- * issued.
- * For 32-bit guests, the L4 is not used (as there is less pagetables), so
- * instead use L3.
- * At this point the pagetables can be modified using the MMU_NORMAL_PT_UPDATE
- * hypercall. Also if so desired the OS can also try to write to the PTE
- * and be trapped by the hypervisor (as the PTE entry is RO).
- *
- * To deallocate the pages, the operations are the reverse of the steps
- * mentioned above. The argument is MMUEXT_UNPIN_TABLE for all levels and the
- * pagetable MUST not be in use (meaning that the cr3 is not set to it).
- *
- * ptr[1:0] == MMU_MACHPHYS_UPDATE:
- * Updates an entry in the machine->pseudo-physical mapping table.
- * ptr[:2] -- Machine address within the frame whose mapping to modify.
- * The frame must belong to the FD, if one is specified.
- * val -- Value to write into the mapping entry.
- *
- * ptr[1:0] == MMU_PT_UPDATE_PRESERVE_AD:
- * As MMU_NORMAL_PT_UPDATE above, but A/D bits currently in the PTE are ORed
- * with those in @val.
- *
- * @val is usually the machine frame number along with some attributes.
- * The attributes by default follow the architecture defined bits. Meaning that
- * if this is a X86_64 machine and four page table layout is used, the layout
- * of val is:
- * - 63 if set means No execute (NX)
- * - 46-13 the machine frame number
- * - 12 available for guest
- * - 11 available for guest
- * - 10 available for guest
- * - 9 available for guest
- * - 8 global
- * - 7 PAT (PSE is disabled, must use hypercall to make 4MB or 2MB pages)
- * - 6 dirty
- * - 5 accessed
- * - 4 page cached disabled
- * - 3 page write through
- * - 2 userspace accessible
- * - 1 writeable
- * - 0 present
- *
- * The one bits that does not fit with the default layout is the PAGE_PSE
- * also called PAGE_PAT). The MMUEXT_[UN]MARK_SUPER arguments to the
- * HYPERVISOR_mmuext_op serve as mechanism to set a pagetable to be 4MB
- * (or 2MB) instead of using the PAGE_PSE bit.
- *
- * The reason that the PAGE_PSE (bit 7) is not being utilized is due to Xen
- * using it as the Page Attribute Table (PAT) bit - for details on it please
- * refer to Intel SDM 10.12. The PAT allows to set the caching attributes of
- * pages instead of using MTRRs.
- *
- * The PAT MSR is as follows (it is a 64-bit value, each entry is 8 bits):
- * PAT4 PAT0
- * +-----+-----+----+----+----+-----+----+----+
- * | UC | UC- | WC | WB | UC | UC- | WC | WB | <= Linux
- * +-----+-----+----+----+----+-----+----+----+
- * | UC | UC- | WT | WB | UC | UC- | WT | WB | <= BIOS (default when machine boots)
- * +-----+-----+----+----+----+-----+----+----+
- * | rsv | rsv | WP | WC | UC | UC- | WT | WB | <= Xen
- * +-----+-----+----+----+----+-----+----+----+
- *
- * The lookup of this index table translates to looking up
- * Bit 7, Bit 4, and Bit 3 of val entry:
- *
- * PAT/PSE (bit 7) ... PCD (bit 4) .. PWT (bit 3).
- *
- * If all bits are off, then we are using PAT0. If bit 3 turned on,
- * then we are using PAT1, if bit 3 and bit 4, then PAT2..
- *
- * As you can see, the Linux PAT1 translates to PAT4 under Xen. Which means
- * that if a guest that follows Linux's PAT setup and would like to set Write
- * Combined on pages it MUST use PAT4 entry. Meaning that Bit 7 (PAGE_PAT) is
- * set. For example, under Linux it only uses PAT0, PAT1, and PAT2 for the
- * caching as:
- *
- * WB = none (so PAT0)
- * WC = PWT (bit 3 on)
- * UC = PWT | PCD (bit 3 and 4 are on).
- *
- * To make it work with Xen, it needs to translate the WC bit as so:
- *
- * PWT (so bit 3 on) --> PAT (so bit 7 is on) and clear bit 3
- *
- * And to translate back it would:
- *
- * PAT (bit 7 on) --> PWT (bit 3 on) and clear bit 7.
- */
-#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */
-#define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */
-#define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */
-
-/*
- * MMU EXTENDED OPERATIONS
- *
- * ` enum neg_errnoval
- * ` HYPERVISOR_mmuext_op(mmuext_op_t uops[],
- * ` unsigned int count,
- * ` unsigned int *pdone,
- * ` unsigned int foreigndom)
- */
-/* HYPERVISOR_mmuext_op() accepts a list of mmuext_op structures.
- * A foreigndom (FD) can be specified (or DOMID_SELF for none).
- * Where the FD has some effect, it is described below.
- *
- * cmd: MMUEXT_(UN)PIN_*_TABLE
- * mfn: Machine frame number to be (un)pinned as a p.t. page.
- * The frame must belong to the FD, if one is specified.
- *
- * cmd: MMUEXT_NEW_BASEPTR
- * mfn: Machine frame number of new page-table base to install in MMU.
- *
- * cmd: MMUEXT_NEW_USER_BASEPTR [x86/64 only]
- * mfn: Machine frame number of new page-table base to install in MMU
- * when in user space.
- *
- * cmd: MMUEXT_TLB_FLUSH_LOCAL
- * No additional arguments. Flushes local TLB.
- *
- * cmd: MMUEXT_INVLPG_LOCAL
- * linear_addr: Linear address to be flushed from the local TLB.
- *
- * cmd: MMUEXT_TLB_FLUSH_MULTI
- * vcpumask: Pointer to bitmap of VCPUs to be flushed.
- *
- * cmd: MMUEXT_INVLPG_MULTI
- * linear_addr: Linear address to be flushed.
- * vcpumask: Pointer to bitmap of VCPUs to be flushed.
- *
- * cmd: MMUEXT_TLB_FLUSH_ALL
- * No additional arguments. Flushes all VCPUs' TLBs.
- *
- * cmd: MMUEXT_INVLPG_ALL
- * linear_addr: Linear address to be flushed from all VCPUs' TLBs.
- *
- * cmd: MMUEXT_FLUSH_CACHE
- * No additional arguments. Writes back and flushes cache contents.
- *
- * cmd: MMUEXT_FLUSH_CACHE_GLOBAL
- * No additional arguments. Writes back and flushes cache contents
- * on all CPUs in the system.
- *
- * cmd: MMUEXT_SET_LDT
- * linear_addr: Linear address of LDT base (NB. must be page-aligned).
- * nr_ents: Number of entries in LDT.
- *
- * cmd: MMUEXT_CLEAR_PAGE
- * mfn: Machine frame number to be cleared.
- *
- * cmd: MMUEXT_COPY_PAGE
- * mfn: Machine frame number of the destination page.
- * src_mfn: Machine frame number of the source page.
- *
- * cmd: MMUEXT_[UN]MARK_SUPER
- * mfn: Machine frame number of head of superpage to be [un]marked.
- */
-/* ` enum mmuext_cmd { */
-#define MMUEXT_PIN_L1_TABLE 0
-#define MMUEXT_PIN_L2_TABLE 1
-#define MMUEXT_PIN_L3_TABLE 2
-#define MMUEXT_PIN_L4_TABLE 3
-#define MMUEXT_UNPIN_TABLE 4
-#define MMUEXT_NEW_BASEPTR 5
-#define MMUEXT_TLB_FLUSH_LOCAL 6
-#define MMUEXT_INVLPG_LOCAL 7
-#define MMUEXT_TLB_FLUSH_MULTI 8
-#define MMUEXT_INVLPG_MULTI 9
-#define MMUEXT_TLB_FLUSH_ALL 10
-#define MMUEXT_INVLPG_ALL 11
-#define MMUEXT_FLUSH_CACHE 12
-#define MMUEXT_SET_LDT 13
-#define MMUEXT_NEW_USER_BASEPTR 15
-#define MMUEXT_CLEAR_PAGE 16
-#define MMUEXT_COPY_PAGE 17
-#define MMUEXT_FLUSH_CACHE_GLOBAL 18
-#define MMUEXT_MARK_SUPER 19
-#define MMUEXT_UNMARK_SUPER 20
-/* ` } */
-
-#ifndef __ASSEMBLY__
-struct mmuext_op {
- unsigned int cmd; /* => enum mmuext_cmd */
- union {
- /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR
- * CLEAR_PAGE, COPY_PAGE, [UN]MARK_SUPER */
- xen_pfn_t mfn;
- /* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */
- unsigned long linear_addr;
- } arg1;
- union {
- /* SET_LDT */
- unsigned int nr_ents;
- /* TLB_FLUSH_MULTI, INVLPG_MULTI */
-#if __XEN_INTERFACE_VERSION__ >= 0x00030205
- XEN_GUEST_HANDLE(const_void) vcpumask;
-#else
- const void *vcpumask;
-#endif
- /* COPY_PAGE */
- xen_pfn_t src_mfn;
- } arg2;
-};
-typedef struct mmuext_op mmuext_op_t;
-DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
-#endif
-
-/*
- * ` enum neg_errnoval
- * ` HYPERVISOR_update_va_mapping(unsigned long va, u64 val,
- * ` enum uvm_flags flags)
- * `
- * ` enum neg_errnoval
- * ` HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, u64 val,
- * ` enum uvm_flags flags,
- * ` domid_t domid)
- * `
- * ` @va: The virtual address whose mapping we want to change
- * ` @val: The new page table entry, must contain a machine address
- * ` @flags: Control TLB flushes
- */
-/* These are passed as 'flags' to update_va_mapping. They can be ORed. */
-/* When specifying UVMF_MULTI, also OR in a pointer to a CPU bitmap. */
-/* UVMF_LOCAL is merely UVMF_MULTI with a NULL bitmap pointer. */
-/* ` enum uvm_flags { */
-#define UVMF_NONE (0UL<<0) /* No flushing at all. */
-#define UVMF_TLB_FLUSH (1UL<<0) /* Flush entire TLB(s). */
-#define UVMF_INVLPG (2UL<<0) /* Flush only one entry. */
-#define UVMF_FLUSHTYPE_MASK (3UL<<0)
-#define UVMF_MULTI (0UL<<2) /* Flush subset of TLBs. */
-#define UVMF_LOCAL (0UL<<2) /* Flush local TLB. */
-#define UVMF_ALL (1UL<<2) /* Flush all TLBs. */
-/* ` } */
-
-/*
- * Commands to HYPERVISOR_console_io().
- */
-#define CONSOLEIO_write 0
-#define CONSOLEIO_read 1
-
-/*
- * Commands to HYPERVISOR_vm_assist().
- */
-#define VMASST_CMD_enable 0
-#define VMASST_CMD_disable 1
-
-/* x86/32 guests: simulate full 4GB segment limits. */
-#define VMASST_TYPE_4gb_segments 0
-
-/* x86/32 guests: trap (vector 15) whenever above vmassist is used. */
-#define VMASST_TYPE_4gb_segments_notify 1
-
-/*
- * x86 guests: support writes to bottom-level PTEs.
- * NB1. Page-directory entries cannot be written.
- * NB2. Guest must continue to remove all writable mappings of PTEs.
- */
-#define VMASST_TYPE_writable_pagetables 2
-
-/* x86/PAE guests: support PDPTs above 4GB. */
-#define VMASST_TYPE_pae_extended_cr3 3
-
-#define MAX_VMASST_TYPE 3
-
-#ifndef __ASSEMBLY__
-
-typedef uint16_t domid_t;
-
-/* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary domains. */
-#define DOMID_FIRST_RESERVED (0x7FF0U)
-
-/* DOMID_SELF is used in certain contexts to refer to oneself. */
-#define DOMID_SELF (0x7FF0U)
-
-/*
- * DOMID_IO is used to restrict page-table updates to mapping I/O memory.
- * Although no Foreign Domain need be specified to map I/O pages, DOMID_IO
- * is useful to ensure that no mappings to the OS's own heap are accidentally
- * installed. (e.g., in Linux this could cause havoc as reference counts
- * aren't adjusted on the I/O-mapping code path).
- * This only makes sense in MMUEXT_SET_FOREIGNDOM, but in that context can
- * be specified by any calling domain.
- */
-#define DOMID_IO (0x7FF1U)
-
-/*
- * DOMID_XEN is used to allow privileged domains to map restricted parts of
- * Xen's heap space (e.g., the machine_to_phys table).
- * This only makes sense in MMUEXT_SET_FOREIGNDOM, and is only permitted if
- * the caller is privileged.
- */
-#define DOMID_XEN (0x7FF2U)
-
-/*
- * DOMID_COW is used as the owner of sharable pages */
-#define DOMID_COW (0x7FF3U)
-
-/* DOMID_INVALID is used to identify pages with unknown owner. */
-#define DOMID_INVALID (0x7FF4U)
-
-/* Idle domain. */
-#define DOMID_IDLE (0x7FFFU)
-
-/*
- * Send an array of these to HYPERVISOR_mmu_update().
- * NB. The fields are natural pointer/address size for this architecture.
- */
-struct mmu_update {
- uint64_t ptr; /* Machine address of PTE. */
- uint64_t val; /* New contents of PTE. */
-};
-typedef struct mmu_update mmu_update_t;
-DEFINE_XEN_GUEST_HANDLE(mmu_update_t);
-
-/*
- * ` enum neg_errnoval
- * ` HYPERVISOR_multicall(multicall_entry_t call_list[],
- * ` uint32_t nr_calls);
- *
- * NB. The fields are logically the natural register size for this
- * architecture. In cases where xen_ulong_t is larger than this then
- * any unused bits in the upper portion must be zero.
- */
-struct multicall_entry {
- xen_ulong_t op, result;
- xen_ulong_t args[6];
-};
-typedef struct multicall_entry multicall_entry_t;
-DEFINE_XEN_GUEST_HANDLE(multicall_entry_t);
-
-#if __XEN_INTERFACE_VERSION__ < 0x00040400
-/*
- * Event channel endpoints per domain (when using the 2-level ABI):
- * 1024 if a long is 32 bits; 4096 if a long is 64 bits.
- */
-#define NR_EVENT_CHANNELS EVTCHN_2L_NR_CHANNELS
-#endif
-
-struct vcpu_time_info {
- /*
- * Updates to the following values are preceded and followed by an
- * increment of 'version'. The guest can therefore detect updates by
- * looking for changes to 'version'. If the least-significant bit of
- * the version number is set then an update is in progress and the guest
- * must wait to read a consistent set of values.
- * The correct way to interact with the version number is similar to
- * Linux's seqlock: see the implementations of read_seqbegin/read_seqretry.
- */
- uint32_t version;
- uint32_t pad0;
- uint64_t tsc_timestamp; /* TSC at last update of time vals. */
- uint64_t system_time; /* Time, in nanosecs, since boot. */
- /*
- * Current system time:
- * system_time +
- * ((((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul) >> 32)
- * CPU frequency (Hz):
- * ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift
- */
- uint32_t tsc_to_system_mul;
- int8_t tsc_shift;
- int8_t pad1[3];
-}; /* 32 bytes */
-typedef struct vcpu_time_info vcpu_time_info_t;
-
-struct vcpu_info {
- /*
- * 'evtchn_upcall_pending' is written non-zero by Xen to indicate
- * a pending notification for a particular VCPU. It is then cleared
- * by the guest OS /before/ checking for pending work, thus avoiding
- * a set-and-check race. Note that the mask is only accessed by Xen
- * on the CPU that is currently hosting the VCPU. This means that the
- * pending and mask flags can be updated by the guest without special
- * synchronisation (i.e., no need for the x86 LOCK prefix).
- * This may seem suboptimal because if the pending flag is set by
- * a different CPU then an IPI may be scheduled even when the mask
- * is set. However, note:
- * 1. The task of 'interrupt holdoff' is covered by the per-event-
- * channel mask bits. A 'noisy' event that is continually being
- * triggered can be masked at source at this very precise
- * granularity.
- * 2. The main purpose of the per-VCPU mask is therefore to restrict
- * reentrant execution: whether for concurrency control, or to
- * prevent unbounded stack usage. Whatever the purpose, we expect
- * that the mask will be asserted only for short periods at a time,
- * and so the likelihood of a 'spurious' IPI is suitably small.
- * The mask is read before making an event upcall to the guest: a
- * non-zero mask therefore guarantees that the VCPU will not receive
- * an upcall activation. The mask is cleared when the VCPU requests
- * to block: this avoids wakeup-waiting races.
- */
- uint8_t evtchn_upcall_pending;
-#ifdef XEN_HAVE_PV_UPCALL_MASK
- uint8_t evtchn_upcall_mask;
-#else /* XEN_HAVE_PV_UPCALL_MASK */
- uint8_t pad0;
-#endif /* XEN_HAVE_PV_UPCALL_MASK */
- xen_ulong_t evtchn_pending_sel;
- struct arch_vcpu_info arch;
- struct vcpu_time_info time;
-}; /* 64 bytes (x86) */
-#ifndef __XEN__
-typedef struct vcpu_info vcpu_info_t;
-#endif
-
-/*
- * `incontents 200 startofday_shared Start-of-day shared data structure
- * Xen/kernel shared data -- pointer provided in start_info.
- *
- * This structure is defined to be both smaller than a page, and the
- * only data on the shared page, but may vary in actual size even within
- * compatible Xen versions; guests should not rely on the size
- * of this structure remaining constant.
- */
-struct shared_info {
- struct vcpu_info vcpu_info[XEN_LEGACY_MAX_VCPUS];
-
- /*
- * A domain can create "event channels" on which it can send and receive
- * asynchronous event notifications. There are three classes of event that
- * are delivered by this mechanism:
- * 1. Bi-directional inter- and intra-domain connections. Domains must
- * arrange out-of-band to set up a connection (usually by allocating
- * an unbound 'listener' port and avertising that via a storage service
- * such as xenstore).
- * 2. Physical interrupts. A domain with suitable hardware-access
- * privileges can bind an event-channel port to a physical interrupt
- * source.
- * 3. Virtual interrupts ('events'). A domain can bind an event-channel
- * port to a virtual interrupt source, such as the virtual-timer
- * device or the emergency console.
- *
- * Event channels are addressed by a "port index". Each channel is
- * associated with two bits of information:
- * 1. PENDING -- notifies the domain that there is a pending notification
- * to be processed. This bit is cleared by the guest.
- * 2. MASK -- if this bit is clear then a 0->1 transition of PENDING
- * will cause an asynchronous upcall to be scheduled. This bit is only
- * updated by the guest. It is read-only within Xen. If a channel
- * becomes pending while the channel is masked then the 'edge' is lost
- * (i.e., when the channel is unmasked, the guest must manually handle
- * pending notifications as no upcall will be scheduled by Xen).
- *
- * To expedite scanning of pending notifications, any 0->1 pending
- * transition on an unmasked channel causes a corresponding bit in a
- * per-vcpu selector word to be set. Each bit in the selector covers a
- * 'C long' in the PENDING bitfield array.
- */
- xen_ulong_t evtchn_pending[sizeof(xen_ulong_t) * 8];
- xen_ulong_t evtchn_mask[sizeof(xen_ulong_t) * 8];
-
- /*
- * Wallclock time: updated only by control software. Guests should base
- * their gettimeofday() syscall on this wallclock-base value.
- */
- uint32_t wc_version; /* Version counter: see vcpu_time_info_t. */
- uint32_t wc_sec; /* Secs 00:00:00 UTC, Jan 1, 1970. */
- uint32_t wc_nsec; /* Nsecs 00:00:00 UTC, Jan 1, 1970. */
-
- struct arch_shared_info arch;
-
-};
-#ifndef __XEN__
-typedef struct shared_info shared_info_t;
-#endif
-
-/*
- * `incontents 200 startofday Start-of-day memory layout
- *
- * 1. The domain is started within contiguous virtual-memory region.
- * 2. The contiguous region ends on an aligned 4MB boundary.
- * 3. This the order of bootstrap elements in the initial virtual region:
- * a. relocated kernel image
- * b. initial ram disk [mod_start, mod_len]
- * c. list of allocated page frames [mfn_list, nr_pages]
- * (unless relocated due to XEN_ELFNOTE_INIT_P2M)
- * d. start_info_t structure [register ESI (x86)]
- * e. bootstrap page tables [pt_base and CR3 (x86)]
- * f. bootstrap stack [register ESP (x86)]
- * 4. Bootstrap elements are packed together, but each is 4kB-aligned.
- * 5. The initial ram disk may be omitted.
- * 6. The list of page frames forms a contiguous 'pseudo-physical' memory
- * layout for the domain. In particular, the bootstrap virtual-memory
- * region is a 1:1 mapping to the first section of the pseudo-physical map.
- * 7. All bootstrap elements are mapped read-writable for the guest OS. The
- * only exception is the bootstrap page table, which is mapped read-only.
- * 8. There is guaranteed to be at least 512kB padding after the final
- * bootstrap element. If necessary, the bootstrap virtual region is
- * extended by an extra 4MB to ensure this.
- *
- * Note: Prior to 25833:bb85bbccb1c9. ("x86/32-on-64 adjust Dom0 initial page
- * table layout") a bug caused the pt_base (3.e above) and cr3 to not point
- * to the start of the guest page tables (it was offset by two pages).
- * This only manifested itself on 32-on-64 dom0 kernels and not 32-on-64 domU
- * or 64-bit kernels of any colour. The page tables for a 32-on-64 dom0 got
- * allocated in the order: 'first L1','first L2', 'first L3', so the offset
- * to the page table base is by two pages back. The initial domain if it is
- * 32-bit and runs under a 64-bit hypervisor should _NOT_ use two of the
- * pages preceding pt_base and mark them as reserved/unused.
- */
-#ifdef XEN_HAVE_PV_GUEST_ENTRY
-struct start_info {
- /* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME. */
- char magic[32]; /* "xen-<version>-<platform>". */
- unsigned long nr_pages; /* Total pages allocated to this domain. */
- unsigned long shared_info; /* MACHINE address of shared info struct. */
- uint32_t flags; /* SIF_xxx flags. */
- xen_pfn_t store_mfn; /* MACHINE page number of shared page. */
- uint32_t store_evtchn; /* Event channel for store communication. */
- union {
- struct {
- xen_pfn_t mfn; /* MACHINE page number of console page. */
- uint32_t evtchn; /* Event channel for console page. */
- } domU;
- struct {
- uint32_t info_off; /* Offset of console_info struct. */
- uint32_t info_size; /* Size of console_info struct from start.*/
- } dom0;
- } console;
- /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */
- unsigned long pt_base; /* VIRTUAL address of page directory. */
- unsigned long nr_pt_frames; /* Number of bootstrap p.t. frames. */
- unsigned long mfn_list; /* VIRTUAL address of page-frame list. */
- unsigned long mod_start; /* VIRTUAL address of pre-loaded module */
- /* (PFN of pre-loaded module if */
- /* SIF_MOD_START_PFN set in flags). */
- unsigned long mod_len; /* Size (bytes) of pre-loaded module. */
-#define MAX_GUEST_CMDLINE 1024
- int8_t cmd_line[MAX_GUEST_CMDLINE];
- /* The pfn range here covers both page table and p->m table frames. */
- unsigned long first_p2m_pfn;/* 1st pfn forming initial P->M table. */
- unsigned long nr_p2m_frames;/* # of pfns forming initial P->M table. */
-};
-typedef struct start_info start_info_t;
-
-/* New console union for dom0 introduced in 0x00030203. */
-#if __XEN_INTERFACE_VERSION__ < 0x00030203
-#define console_mfn console.domU.mfn
-#define console_evtchn console.domU.evtchn
-#endif
-#endif /* XEN_HAVE_PV_GUEST_ENTRY */
-
-/* These flags are passed in the 'flags' field of start_info_t. */
-#define SIF_PRIVILEGED (1<<0) /* Is the domain privileged? */
-#define SIF_INITDOMAIN (1<<1) /* Is this the initial control domain? */
-#define SIF_MULTIBOOT_MOD (1<<2) /* Is mod_start a multiboot module? */
-#define SIF_MOD_START_PFN (1<<3) /* Is mod_start a PFN? */
-#define SIF_PM_MASK (0xFF<<8) /* reserve 1 byte for xen-pm options */
-
-/*
- * A multiboot module is a package containing modules very similar to a
- * multiboot module array. The only differences are:
- * - the array of module descriptors is by convention simply at the beginning
- * of the multiboot module,
- * - addresses in the module descriptors are based on the beginning of the
- * multiboot module,
- * - the number of modules is determined by a termination descriptor that has
- * mod_start == 0.
- *
- * This permits to both build it statically and reference it in a configuration
- * file, and let the PV guest easily rebase the addresses to virtual addresses
- * and at the same time count the number of modules.
- */
-struct xen_multiboot_mod_list
-{
- /* Address of first byte of the module */
- uint32_t mod_start;
- /* Address of last byte of the module (inclusive) */
- uint32_t mod_end;
- /* Address of zero-terminated command line */
- uint32_t cmdline;
- /* Unused, must be zero */
- uint32_t pad;
-};
-/*
- * `incontents 200 startofday_dom0_console Dom0_console
- *
- * The console structure in start_info.console.dom0
- *
- * This structure includes a variety of information required to
- * have a working VGA/VESA console.
- */
-typedef struct dom0_vga_console_info {
- uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */
-#define XEN_VGATYPE_TEXT_MODE_3 0x03
-#define XEN_VGATYPE_VESA_LFB 0x23
-#define XEN_VGATYPE_EFI_LFB 0x70
-
- union {
- struct {
- /* Font height, in pixels. */
- uint16_t font_height;
- /* Cursor location (column, row). */
- uint16_t cursor_x, cursor_y;
- /* Number of rows and columns (dimensions in characters). */
- uint16_t rows, columns;
- } text_mode_3;
-
- struct {
- /* Width and height, in pixels. */
- uint16_t width, height;
- /* Bytes per scan line. */
- uint16_t bytes_per_line;
- /* Bits per pixel. */
- uint16_t bits_per_pixel;
- /* LFB physical address, and size (in units of 64kB). */
- uint32_t lfb_base;
- uint32_t lfb_size;
- /* RGB mask offsets and sizes, as defined by VBE 1.2+ */
- uint8_t red_pos, red_size;
- uint8_t green_pos, green_size;
- uint8_t blue_pos, blue_size;
- uint8_t rsvd_pos, rsvd_size;
-#if __XEN_INTERFACE_VERSION__ >= 0x00030206
- /* VESA capabilities (offset 0xa, VESA command 0x4f00). */
- uint32_t gbl_caps;
- /* Mode attributes (offset 0x0, VESA command 0x4f01). */
- uint16_t mode_attrs;
-#endif
- } vesa_lfb;
- } u;
-} dom0_vga_console_info_t;
-#define xen_vga_console_info dom0_vga_console_info
-#define xen_vga_console_info_t dom0_vga_console_info_t
-
-typedef uint8_t xen_domain_handle_t[16];
-
-/* Turn a plain number into a C unsigned long constant. */
-#define __mk_unsigned_long(x) x ## UL
-#define mk_unsigned_long(x) __mk_unsigned_long(x)
-
-__DEFINE_XEN_GUEST_HANDLE(uint8, uint8_t);
-__DEFINE_XEN_GUEST_HANDLE(uint16, uint16_t);
-__DEFINE_XEN_GUEST_HANDLE(uint32, uint32_t);
-__DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
-
-#else /* __ASSEMBLY__ */
-
-/* In assembly code we cannot use C numeric constant suffixes. */
-#define mk_unsigned_long(x) x
-
-#endif /* !__ASSEMBLY__ */
-
-/* Default definitions for macros used by domctl/sysctl. */
-#if defined(__XEN__) || defined(__XEN_TOOLS__)
-
-#ifndef uint64_aligned_t
-#define uint64_aligned_t uint64_t
-#endif
-#ifndef XEN_GUEST_HANDLE_64
-#define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name)
-#endif
-
-#ifndef __ASSEMBLY__
-struct xenctl_bitmap {
- XEN_GUEST_HANDLE_64(uint8) bitmap;
- uint32_t nr_bits;
-};
-#endif
-
-#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
-
-#endif /* __XEN_PUBLIC_XEN_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (C) IBM Corp. 2006
- */
-
-#ifndef _XEN_XENCOMM_H_
-#define _XEN_XENCOMM_H_
-
-/* A xencomm descriptor is a scatter/gather list containing physical
- * addresses corresponding to a virtually contiguous memory area. The
- * hypervisor translates these physical addresses to machine addresses to copy
- * to and from the virtually contiguous area.
- */
-
-#define XENCOMM_MAGIC 0x58434F4D /* 'XCOM' */
-#define XENCOMM_INVALID (~0UL)
-
-struct xencomm_desc {
- uint32_t magic;
- uint32_t nr_addrs; /* the number of entries in address[] */
- uint64_t address[0];
-};
-
-#endif /* _XEN_XENCOMM_H_ */
+++ /dev/null
-/******************************************************************************
- * xenoprof.h
- *
- * Interface for enabling system wide profiling based on hardware performance
- * counters
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (C) 2005 Hewlett-Packard Co.
- * Written by Aravind Menon & Jose Renato Santos
- */
-
-#ifndef __XEN_PUBLIC_XENOPROF_H__
-#define __XEN_PUBLIC_XENOPROF_H__
-
-#include "xen.h"
-
-/*
- * Commands to HYPERVISOR_xenoprof_op().
- */
-#define XENOPROF_init 0
-#define XENOPROF_reset_active_list 1
-#define XENOPROF_reset_passive_list 2
-#define XENOPROF_set_active 3
-#define XENOPROF_set_passive 4
-#define XENOPROF_reserve_counters 5
-#define XENOPROF_counter 6
-#define XENOPROF_setup_events 7
-#define XENOPROF_enable_virq 8
-#define XENOPROF_start 9
-#define XENOPROF_stop 10
-#define XENOPROF_disable_virq 11
-#define XENOPROF_release_counters 12
-#define XENOPROF_shutdown 13
-#define XENOPROF_get_buffer 14
-#define XENOPROF_set_backtrace 15
-
-/* AMD IBS support */
-#define XENOPROF_get_ibs_caps 16
-#define XENOPROF_ibs_counter 17
-#define XENOPROF_last_op 17
-
-#define MAX_OPROF_EVENTS 32
-#define MAX_OPROF_DOMAINS 25
-#define XENOPROF_CPU_TYPE_SIZE 64
-
-/* Xenoprof performance events (not Xen events) */
-struct event_log {
- uint64_t eip;
- uint8_t mode;
- uint8_t event;
-};
-
-/* PC value that indicates a special code */
-#define XENOPROF_ESCAPE_CODE (~0ULL)
-/* Transient events for the xenoprof->oprofile cpu buf */
-#define XENOPROF_TRACE_BEGIN 1
-
-/* Xenoprof buffer shared between Xen and domain - 1 per VCPU */
-struct xenoprof_buf {
- uint32_t event_head;
- uint32_t event_tail;
- uint32_t event_size;
- uint32_t vcpu_id;
- uint64_t xen_samples;
- uint64_t kernel_samples;
- uint64_t user_samples;
- uint64_t lost_samples;
- struct event_log event_log[1];
-};
-#ifndef __XEN__
-typedef struct xenoprof_buf xenoprof_buf_t;
-DEFINE_XEN_GUEST_HANDLE(xenoprof_buf_t);
-#endif
-
-struct xenoprof_init {
- int32_t num_events;
- int32_t is_primary;
- char cpu_type[XENOPROF_CPU_TYPE_SIZE];
-};
-typedef struct xenoprof_init xenoprof_init_t;
-DEFINE_XEN_GUEST_HANDLE(xenoprof_init_t);
-
-struct xenoprof_get_buffer {
- int32_t max_samples;
- int32_t nbuf;
- int32_t bufsize;
- uint64_t buf_gmaddr;
-};
-typedef struct xenoprof_get_buffer xenoprof_get_buffer_t;
-DEFINE_XEN_GUEST_HANDLE(xenoprof_get_buffer_t);
-
-struct xenoprof_counter {
- uint32_t ind;
- uint64_t count;
- uint32_t enabled;
- uint32_t event;
- uint32_t hypervisor;
- uint32_t kernel;
- uint32_t user;
- uint64_t unit_mask;
-};
-typedef struct xenoprof_counter xenoprof_counter_t;
-DEFINE_XEN_GUEST_HANDLE(xenoprof_counter_t);
-
-typedef struct xenoprof_passive {
- uint16_t domain_id;
- int32_t max_samples;
- int32_t nbuf;
- int32_t bufsize;
- uint64_t buf_gmaddr;
-} xenoprof_passive_t;
-DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t);
-
-struct xenoprof_ibs_counter {
- uint64_t op_enabled;
- uint64_t fetch_enabled;
- uint64_t max_cnt_fetch;
- uint64_t max_cnt_op;
- uint64_t rand_en;
- uint64_t dispatched_ops;
-};
-typedef struct xenoprof_ibs_counter xenoprof_ibs_counter_t;
-DEFINE_XEN_GUEST_HANDLE(xenoprof_ibs_counter_t);
-
-#endif /* __XEN_PUBLIC_XENOPROF_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/*
- * This file contains the flask_op hypercall commands and definitions.
- *
- * Author: George Coker, <gscoker@alpha.ncsc.mil>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __FLASK_OP_H__
-#define __FLASK_OP_H__
-
-#define XEN_FLASK_INTERFACE_VERSION 1
-
-struct xen_flask_load {
- XEN_GUEST_HANDLE(char) buffer;
- uint32_t size;
-};
-
-struct xen_flask_setenforce {
- uint32_t enforcing;
-};
-
-struct xen_flask_sid_context {
- /* IN/OUT: sid to convert to/from string */
- uint32_t sid;
- /* IN: size of the context buffer
- * OUT: actual size of the output context string
- */
- uint32_t size;
- XEN_GUEST_HANDLE(char) context;
-};
-
-struct xen_flask_access {
- /* IN: access request */
- uint32_t ssid;
- uint32_t tsid;
- uint32_t tclass;
- uint32_t req;
- /* OUT: AVC data */
- uint32_t allowed;
- uint32_t audit_allow;
- uint32_t audit_deny;
- uint32_t seqno;
-};
-
-struct xen_flask_transition {
- /* IN: transition SIDs and class */
- uint32_t ssid;
- uint32_t tsid;
- uint32_t tclass;
- /* OUT: new SID */
- uint32_t newsid;
-};
-
-struct xen_flask_userlist {
- /* IN: starting SID for list */
- uint32_t start_sid;
- /* IN: size of user string and output buffer
- * OUT: number of SIDs returned */
- uint32_t size;
- union {
- /* IN: user to enumerate SIDs */
- XEN_GUEST_HANDLE(char) user;
- /* OUT: SID list */
- XEN_GUEST_HANDLE(uint32) sids;
- } u;
-};
-
-struct xen_flask_boolean {
- /* IN/OUT: numeric identifier for boolean [GET/SET]
- * If -1, name will be used and bool_id will be filled in. */
- uint32_t bool_id;
- /* OUT: current enforcing value of boolean [GET/SET] */
- uint8_t enforcing;
- /* OUT: pending value of boolean [GET/SET] */
- uint8_t pending;
- /* IN: new value of boolean [SET] */
- uint8_t new_value;
- /* IN: commit new value instead of only setting pending [SET] */
- uint8_t commit;
- /* IN: size of boolean name buffer [GET/SET]
- * OUT: actual size of name [GET only] */
- uint32_t size;
- /* IN: if bool_id is -1, used to find boolean [GET/SET]
- * OUT: textual name of boolean [GET only]
- */
- XEN_GUEST_HANDLE(char) name;
-};
-
-struct xen_flask_setavc_threshold {
- /* IN */
- uint32_t threshold;
-};
-
-struct xen_flask_hash_stats {
- /* OUT */
- uint32_t entries;
- uint32_t buckets_used;
- uint32_t buckets_total;
- uint32_t max_chain_len;
-};
-
-struct xen_flask_cache_stats {
- /* IN */
- uint32_t cpu;
- /* OUT */
- uint32_t lookups;
- uint32_t hits;
- uint32_t misses;
- uint32_t allocations;
- uint32_t reclaims;
- uint32_t frees;
-};
-
-struct xen_flask_ocontext {
- /* IN */
- uint32_t ocon;
- uint32_t sid;
- uint64_t low, high;
-};
-
-struct xen_flask_peersid {
- /* IN */
- evtchn_port_t evtchn;
- /* OUT */
- uint32_t sid;
-};
-
-struct xen_flask_relabel {
- /* IN */
- uint32_t domid;
- uint32_t sid;
-};
-
-struct xen_flask_op {
- uint32_t cmd;
-#define FLASK_LOAD 1
-#define FLASK_GETENFORCE 2
-#define FLASK_SETENFORCE 3
-#define FLASK_CONTEXT_TO_SID 4
-#define FLASK_SID_TO_CONTEXT 5
-#define FLASK_ACCESS 6
-#define FLASK_CREATE 7
-#define FLASK_RELABEL 8
-#define FLASK_USER 9
-#define FLASK_POLICYVERS 10
-#define FLASK_GETBOOL 11
-#define FLASK_SETBOOL 12
-#define FLASK_COMMITBOOLS 13
-#define FLASK_MLS 14
-#define FLASK_DISABLE 15
-#define FLASK_GETAVC_THRESHOLD 16
-#define FLASK_SETAVC_THRESHOLD 17
-#define FLASK_AVC_HASHSTATS 18
-#define FLASK_AVC_CACHESTATS 19
-#define FLASK_MEMBER 20
-#define FLASK_ADD_OCONTEXT 21
-#define FLASK_DEL_OCONTEXT 22
-#define FLASK_GET_PEER_SID 23
-#define FLASK_RELABEL_DOMAIN 24
- uint32_t interface_version; /* XEN_FLASK_INTERFACE_VERSION */
- union {
- struct xen_flask_load load;
- struct xen_flask_setenforce enforce;
- /* FLASK_CONTEXT_TO_SID and FLASK_SID_TO_CONTEXT */
- struct xen_flask_sid_context sid_context;
- struct xen_flask_access access;
- /* FLASK_CREATE, FLASK_RELABEL, FLASK_MEMBER */
- struct xen_flask_transition transition;
- struct xen_flask_userlist userlist;
- /* FLASK_GETBOOL, FLASK_SETBOOL */
- struct xen_flask_boolean boolean;
- struct xen_flask_setavc_threshold setavc_threshold;
- struct xen_flask_hash_stats hash_stats;
- struct xen_flask_cache_stats cache_stats;
- /* FLASK_ADD_OCONTEXT, FLASK_DEL_OCONTEXT */
- struct xen_flask_ocontext ocontext;
- struct xen_flask_peersid peersid;
- struct xen_flask_relabel relabel;
- } u;
-};
-typedef struct xen_flask_op xen_flask_op_t;
-DEFINE_XEN_GUEST_HANDLE(xen_flask_op_t);
-
-#endif
+++ /dev/null
-#ifndef XENBUS_H__
-#define XENBUS_H__
-
-#include <xen/io/xenbus.h>
-
-typedef unsigned long xenbus_transaction_t;
-#define XBT_NIL ((xenbus_transaction_t)0)
-
-#ifdef CONFIG_XENBUS
-/* Initialize the XenBus system. */
-void init_xenbus(void);
-#else
-static inline void init_xenbus(void)
-{
-}
-#endif
-
-/* Read the value associated with a path. Returns a malloc'd error
- string on failure and sets *value to NULL. On success, *value is
- set to a malloc'd copy of the value. */
-char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value);
-
-/* Watch event queue */
-struct xenbus_event {
- /* Keep these two as this for xs.c */
- char *path;
- char *token;
- struct xenbus_event *next;
-};
-typedef struct xenbus_event *xenbus_event_queue;
-
-char *xenbus_watch_path_token(xenbus_transaction_t xbt, const char *path, const char *token, xenbus_event_queue *events);
-char *xenbus_unwatch_path_token(xenbus_transaction_t xbt, const char *path, const char *token);
-extern struct wait_queue_head xenbus_watch_queue;
-void xenbus_wait_for_watch(xenbus_event_queue *queue);
-char **xenbus_wait_for_watch_return(xenbus_event_queue *queue);
-char* xenbus_wait_for_value(const char *path, const char *value, xenbus_event_queue *queue);
-char *xenbus_wait_for_state_change(const char* path, XenbusState *state, xenbus_event_queue *queue);
-char *xenbus_switch_state(xenbus_transaction_t xbt, const char* path, XenbusState state);
-
-/* When no token is provided, use a global queue. */
-#define XENBUS_WATCH_PATH_TOKEN "xenbus_watch_path"
-extern xenbus_event_queue xenbus_events;
-#define xenbus_watch_path(xbt, path) xenbus_watch_path_token(xbt, path, XENBUS_WATCH_PATH_TOKEN, NULL)
-#define xenbus_unwatch_path(xbt, path) xenbus_unwatch_path_token(xbt, path, XENBUS_WATCH_PATH_TOKEN)
-
-
-/* Associates a value with a path. Returns a malloc'd error string on
- failure. */
-char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value);
-
-struct write_req {
- const void *data;
- unsigned len;
-};
-
-/* Send a message to xenbus, in the same fashion as xb_write, and
- block waiting for a reply. The reply is malloced and should be
- freed by the caller. */
-struct xsd_sockmsg *
-xenbus_msg_reply(int type,
- xenbus_transaction_t trans,
- struct write_req *io,
- int nr_reqs);
-
-/* Removes the value associated with a path. Returns a malloc'd error
- string on failure. */
-char *xenbus_rm(xenbus_transaction_t xbt, const char *path);
-
-/* List the contents of a directory. Returns a malloc'd error string
- on failure and sets *contents to NULL. On success, *contents is
- set to a malloc'd array of pointers to malloc'd strings. The array
- is NULL terminated. May block. */
-char *xenbus_ls(xenbus_transaction_t xbt, const char *prefix, char ***contents);
-
-/* Reads permissions associated with a path. Returns a malloc'd error
- string on failure and sets *value to NULL. On success, *value is
- set to a malloc'd copy of the value. */
-char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value);
-
-/* Sets the permissions associated with a path. Returns a malloc'd
- error string on failure. */
-char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t dom, char perm);
-
-/* Start a xenbus transaction. Returns the transaction in xbt on
- success or a malloc'd error string otherwise. */
-char *xenbus_transaction_start(xenbus_transaction_t *xbt);
-
-/* End a xenbus transaction. Returns a malloc'd error string if it
- fails. abort says whether the transaction should be aborted.
- Returns 1 in *retry iff the transaction should be retried. */
-char *xenbus_transaction_end(xenbus_transaction_t, int abort,
- int *retry);
-
-/* Read path and parse it as an integer. Returns -1 on error. */
-int xenbus_read_integer(const char *path);
-
-/* Read path and parse it as 16 byte uuid. Returns 1 if
- * read and parsing were successful, 0 if not */
-int xenbus_read_uuid(const char* path, unsigned char uuid[16]);
-
-/* Contraction of snprintf and xenbus_write(path/node). */
-char* xenbus_printf(xenbus_transaction_t xbt,
- const char* node, const char* path,
- const char* fmt, ...)
- __attribute__((__format__(printf, 4, 5)));
-
-/* Utility function to figure out our domain id */
-domid_t xenbus_get_self_id(void);
-
-#ifdef CONFIG_XENBUS
-/* Reset the XenBus system. */
-void fini_xenbus(void);
-#else
-static inline void fini_xenbus(void)
-{
-}
-#endif
-
-#endif /* XENBUS_H__ */
+++ /dev/null
-#ifndef __XMALLOC_H__
-#define __XMALLOC_H__
-
-#ifdef HAVE_LIBC
-
-#include <stdlib.h>
-#include <malloc.h>
-/* Allocate space for typed object. */
-#define _xmalloc(size, align) memalign(align, size)
-#define xfree(ptr) free(ptr)
-
-#else
-
-#include <limits.h>
-
-#define DEFAULT_ALIGN (sizeof(unsigned long))
-
-extern void *malloc(size_t size);
-extern void *realloc(void *ptr, size_t size);
-extern void free(void *ptr);
-
-/* Free memory from any xmalloc*() call. */
-extern void xfree(const void *);
-
-/* Underlying functions */
-extern void *_xmalloc(size_t size, size_t align);
-
-#endif
-
-static inline void *_xmalloc_array(size_t size, size_t align, size_t num)
-{
- /* Check for overflow. */
- if (size && num > UINT_MAX / size)
- return NULL;
- return _xmalloc(size * num, align);
-}
-
-/* Allocate space for typed object. */
-#define xmalloc(_type) ((_type *)_xmalloc(sizeof(_type), __alignof__(_type)))
-
-/* Allocate space for array of typed objects. */
-#define xmalloc_array(_type, _num) ((_type *)_xmalloc_array(sizeof(_type), __alignof__(_type), _num))
-
-#endif /* __XMALLOC_H__ */
+++ /dev/null
-/******************************************************************************
- * kernel.c
- *
- * Assorted crap goes here, including the initial C entry point, jumped at
- * from head.S.
- *
- * Copyright (c) 2002-2003, K A Fraser & R Neugebauer
- * Copyright (c) 2005, Grzegorz Milos, Intel Research Cambridge
- * Copyright (c) 2006, Robert Kaiser, FH Wiesbaden
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <mini-os/os.h>
-#include <mini-os/kernel.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/mm.h>
-#include <mini-os/events.h>
-#include <mini-os/time.h>
-#include <mini-os/types.h>
-#include <mini-os/lib.h>
-#include <mini-os/sched.h>
-#include <mini-os/xenbus.h>
-#include <mini-os/gnttab.h>
-#include <mini-os/netfront.h>
-#include <mini-os/blkfront.h>
-#include <mini-os/fbfront.h>
-#include <mini-os/pcifront.h>
-#include <mini-os/xmalloc.h>
-#include <fcntl.h>
-#include <xen/features.h>
-#include <xen/version.h>
-
-uint8_t xen_features[XENFEAT_NR_SUBMAPS * 32];
-
-void setup_xen_features(void)
-{
- xen_feature_info_t fi;
- int i, j;
-
- for (i = 0; i < XENFEAT_NR_SUBMAPS; i++)
- {
- fi.submap_idx = i;
- if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0)
- break;
-
- for (j=0; j<32; j++)
- xen_features[i*32+j] = !!(fi.submap & 1<<j);
- }
-}
-
-#ifdef CONFIG_XENBUS
-/* This should be overridden by the application we are linked against. */
-__attribute__((weak)) void app_shutdown(unsigned reason)
-{
- struct sched_shutdown sched_shutdown = { .reason = reason };
- printk("Shutdown requested: %d\n", reason);
- HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
-}
-
-static void shutdown_thread(void *p)
-{
- const char *path = "control/shutdown";
- const char *token = path;
- xenbus_event_queue events = NULL;
- char *shutdown = NULL, *err;
- unsigned int shutdown_reason;
- xenbus_watch_path_token(XBT_NIL, path, token, &events);
- while ((err = xenbus_read(XBT_NIL, path, &shutdown)) != NULL || !strcmp(shutdown, ""))
- {
- free(err);
- free(shutdown);
- shutdown = NULL;
- xenbus_wait_for_watch(&events);
- }
- err = xenbus_unwatch_path_token(XBT_NIL, path, token);
- free(err);
- err = xenbus_write(XBT_NIL, path, "");
- free(err);
- printk("Shutting down (%s)\n", shutdown);
-
- if (!strcmp(shutdown, "poweroff"))
- shutdown_reason = SHUTDOWN_poweroff;
- else if (!strcmp(shutdown, "reboot"))
- shutdown_reason = SHUTDOWN_reboot;
- else
- /* Unknown */
- shutdown_reason = SHUTDOWN_crash;
- app_shutdown(shutdown_reason);
- free(shutdown);
-}
-#endif
-
-
-/* This should be overridden by the application we are linked against. */
-__attribute__((weak)) int app_main(start_info_t *si)
-{
- printk("kernel.c: dummy main: start_info=%p\n", si);
- return 0;
-}
-
-void start_kernel(void)
-{
- /* Set up events. */
- init_events();
-
- /* ENABLE EVENT DELIVERY. This is disabled at start of day. */
- local_irq_enable();
-
- setup_xen_features();
-
- /* Init memory management. */
- init_mm();
-
- /* Init time and timers. */
- init_time();
-
- /* Init the console driver. */
- init_console();
-
- /* Init grant tables */
- init_gnttab();
-
- /* Init scheduler. */
- init_sched();
-
- /* Init XenBus */
- init_xenbus();
-
-#ifdef CONFIG_XENBUS
- create_thread("shutdown", shutdown_thread, NULL);
-#endif
-
- /* Call (possibly overridden) app_main() */
- app_main(&start_info);
-
- /* Everything initialised, start idle thread */
- run_idle_thread();
-}
-
-void stop_kernel(void)
-{
- /* TODO: fs import */
-
- local_irq_disable();
-
- /* Reset grant tables */
- fini_gnttab();
-
- /* Reset XenBus */
- fini_xenbus();
-
- /* Reset timers */
- fini_time();
-
- /* Reset memory management. */
- fini_mm();
-
- /* Reset events. */
- fini_events();
-
- /* Reset arch details */
- arch_fini();
-}
-
-/*
- * do_exit: This is called whenever an IRET fails in entry.S.
- * This will generally be because an application has got itself into
- * a really bad state (probably a bad CS or SS). It must be killed.
- * Of course, minimal OS doesn't have applications :-)
- */
-
-void do_exit(void)
-{
- printk("Do_exit called!\n");
- arch_do_exit();
- for( ;; )
- {
- struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_crash };
- HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
- }
-}
+++ /dev/null
-#ifndef HAVE_LIBC
-#include <ctype.h>
-
-unsigned char _ctype[] = {
-_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
-_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
-_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
-_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
-_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
-_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
-_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
-_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
-_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
-_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
-_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
-_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
-_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
-_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
-_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
-_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
-_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
-_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
-_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
-_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
-_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
-_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
-#endif
+++ /dev/null
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
- *
- * File: math.c
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes:
- *
- * Date: Aug 2003
- *
- * Environment: Xen Minimal OS
- * Description: Library functions for 64bit arith and other
- * from freebsd, files in sys/libkern/ (qdivrem.c, etc)
- *
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This software was developed by the Computer Systems Engineering group
- * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
- * contributed to Berkeley.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
-*/
-
-#include <mini-os/types.h>
-#include <mini-os/lib.h>
-#include <mini-os/time.h>
-
-/* XXX RN: Yuck hardcoded endianess :) */
-#define _QUAD_HIGHWORD 1
-#define _QUAD_LOWWORD 0
-
-/*
- * From
- * @(#)quad.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * Depending on the desired operation, we view a `long long' (aka quad_t) in
- * one or more of the following formats.
- */
-union uu {
- quad_t q; /* as a (signed) quad */
- quad_t uq; /* as an unsigned quad */
- int32_t sl[2]; /* as two signed longs */
- uint32_t ul[2]; /* as two unsigned longs */
-};
-
-/*
- * Define high and low longwords.
- */
-#define H _QUAD_HIGHWORD
-#define L _QUAD_LOWWORD
-
-/*
- * Total number of bits in an quad_t and in the pieces that make it up.
- * These are used for shifting, and also below for halfword extraction
- * and assembly.
- */
-#ifndef HAVE_LIBC
-#define CHAR_BIT 8 /* number of bits in a char */
-#endif
-#define QUAD_BITS (sizeof(quad_t) * CHAR_BIT)
-#define LONG_BITS (sizeof(int32_t) * CHAR_BIT)
-#define HALF_BITS (sizeof(int32_t) * CHAR_BIT / 2)
-
-/*
- * Extract high and low shortwords from longword, and move low shortword of
- * longword to upper half of int32_t, i.e., produce the upper longword of
- * ((quad_t)(x) << (number_of_bits_in_long/2)). (`x' must actually be uint32_t.)
- *
- * These are used in the multiply code, to split a longword into upper
- * and lower halves, and to reassemble a product as a quad_t, shifted left
- * (sizeof(int32_t)*CHAR_BIT/2).
- */
-#define HHALF(x) ((x) >> HALF_BITS)
-#define LHALF(x) ((x) & ((1UL << HALF_BITS) - 1))
-#define LHUP(x) ((x) << HALF_BITS)
-
-
-/*
- * From
- * qdivrem.c
- */
-
-/*
- * Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed),
- * section 4.3.1, pp. 257--259.
- */
-#define B (1UL << HALF_BITS) /* digit base */
-
-/* Combine two `digits' to make a single two-digit number. */
-#define COMBINE(a, b) (((uint32_t)(a) << HALF_BITS) | (b))
-
-/* select a type for digits in base B: */
-typedef uint16_t digit;
-
-/*
- * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
- * `fall out' the left (there never will be any such anyway).
- * We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS.
- */
-static void
-shl(register digit *p, register int len, register int sh)
-{
- register int i;
-
- for (i = 0; i < len; i++)
- p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh));
- p[i] = LHALF(p[i] << sh);
-}
-
-/*
- * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
- *
- * We do this in base 2-sup-HALF_BITS, so that all intermediate products
- * fit within uint32_t. As a consequence, the maximum length dividend and
- * divisor are 4 `digits' in this base (they are shorter if they have
- * leading zeros).
- */
-u_quad_t
-__qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq)
-{
- union uu tmp;
- digit *u, *v, *q;
- register digit v1, v2;
- uint32_t qhat, rhat, t;
- int m, n, d, j, i;
- digit uspace[5], vspace[5], qspace[5];
-
- /*
- * Take care of special cases: divide by zero, and u < v.
- */
- if (vq == 0) {
- /* divide by zero. */
- static volatile const unsigned int zero = 0;
-
- tmp.ul[H] = tmp.ul[L] = 1 / zero;
- if (arq)
- *arq = uq;
- return (tmp.q);
- }
- if (uq < vq) {
- if (arq)
- *arq = uq;
- return (0);
- }
- u = &uspace[0];
- v = &vspace[0];
- q = &qspace[0];
-
- /*
- * Break dividend and divisor into digits in base B, then
- * count leading zeros to determine m and n. When done, we
- * will have:
- * u = (u[1]u[2]...u[m+n]) sub B
- * v = (v[1]v[2]...v[n]) sub B
- * v[1] != 0
- * 1 < n <= 4 (if n = 1, we use a different division algorithm)
- * m >= 0 (otherwise u < v, which we already checked)
- * m + n = 4
- * and thus
- * m = 4 - n <= 2
- */
- tmp.uq = uq;
- u[0] = 0;
- u[1] = HHALF(tmp.ul[H]);
- u[2] = LHALF(tmp.ul[H]);
- u[3] = HHALF(tmp.ul[L]);
- u[4] = LHALF(tmp.ul[L]);
- tmp.uq = vq;
- v[1] = HHALF(tmp.ul[H]);
- v[2] = LHALF(tmp.ul[H]);
- v[3] = HHALF(tmp.ul[L]);
- v[4] = LHALF(tmp.ul[L]);
- for (n = 4; v[1] == 0; v++) {
- if (--n == 1) {
- uint32_t rbj; /* r*B+u[j] (not root boy jim) */
- digit q1, q2, q3, q4;
-
- /*
- * Change of plan, per exercise 16.
- * r = 0;
- * for j = 1..4:
- * q[j] = floor((r*B + u[j]) / v),
- * r = (r*B + u[j]) % v;
- * We unroll this completely here.
- */
- t = v[2]; /* nonzero, by definition */
- q1 = u[1] / t;
- rbj = COMBINE(u[1] % t, u[2]);
- q2 = rbj / t;
- rbj = COMBINE(rbj % t, u[3]);
- q3 = rbj / t;
- rbj = COMBINE(rbj % t, u[4]);
- q4 = rbj / t;
- if (arq)
- *arq = rbj % t;
- tmp.ul[H] = COMBINE(q1, q2);
- tmp.ul[L] = COMBINE(q3, q4);
- return (tmp.q);
- }
- }
-
- /*
- * By adjusting q once we determine m, we can guarantee that
- * there is a complete four-digit quotient at &qspace[1] when
- * we finally stop.
- */
- for (m = 4 - n; u[1] == 0; u++)
- m--;
- for (i = 4 - m; --i >= 0;)
- q[i] = 0;
- q += 4 - m;
-
- /*
- * Here we run Program D, translated from MIX to C and acquiring
- * a few minor changes.
- *
- * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
- */
- d = 0;
- for (t = v[1]; t < B / 2; t <<= 1)
- d++;
- if (d > 0) {
- shl(&u[0], m + n, d); /* u <<= d */
- shl(&v[1], n - 1, d); /* v <<= d */
- }
- /*
- * D2: j = 0.
- */
- j = 0;
- v1 = v[1]; /* for D3 -- note that v[1..n] are constant */
- v2 = v[2]; /* for D3 */
- do {
- register digit uj0, uj1, uj2;
-
- /*
- * D3: Calculate qhat (\^q, in TeX notation).
- * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
- * let rhat = (u[j]*B + u[j+1]) mod v[1].
- * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
- * decrement qhat and increase rhat correspondingly.
- * Note that if rhat >= B, v[2]*qhat < rhat*B.
- */
- uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
- uj1 = u[j + 1]; /* for D3 only */
- uj2 = u[j + 2]; /* for D3 only */
- if (uj0 == v1) {
- qhat = B;
- rhat = uj1;
- goto qhat_too_big;
- } else {
- uint32_t nn = COMBINE(uj0, uj1);
- qhat = nn / v1;
- rhat = nn % v1;
- }
- while (v2 * qhat > COMBINE(rhat, uj2)) {
- qhat_too_big:
- qhat--;
- if ((rhat += v1) >= B)
- break;
- }
- /*
- * D4: Multiply and subtract.
- * The variable `t' holds any borrows across the loop.
- * We split this up so that we do not require v[0] = 0,
- * and to eliminate a final special case.
- */
- for (t = 0, i = n; i > 0; i--) {
- t = u[i + j] - v[i] * qhat - t;
- u[i + j] = LHALF(t);
- t = (B - HHALF(t)) & (B - 1);
- }
- t = u[j] - t;
- u[j] = LHALF(t);
- /*
- * D5: test remainder.
- * There is a borrow if and only if HHALF(t) is nonzero;
- * in that (rare) case, qhat was too large (by exactly 1).
- * Fix it by adding v[1..n] to u[j..j+n].
- */
- if (HHALF(t)) {
- qhat--;
- for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
- t += u[i + j] + v[i];
- u[i + j] = LHALF(t);
- t = HHALF(t);
- }
- u[j] = LHALF(u[j] + t);
- }
- q[j] = qhat;
- } while (++j <= m); /* D7: loop on j. */
-
- /*
- * If caller wants the remainder, we have to calculate it as
- * u[m..m+n] >> d (this is at most n digits and thus fits in
- * u[m+1..m+n], but we may need more source digits).
- */
- if (arq) {
- if (d) {
- for (i = m + n; i > m; --i)
- u[i] = (u[i] >> d) |
- LHALF(u[i - 1] << (HALF_BITS - d));
- u[i] = 0;
- }
- tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
- tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
- *arq = tmp.q;
- }
-
- tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
- tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
- return (tmp.q);
-}
-
-/*
- * From
- * divdi3.c
- */
-
-/*
- * Divide two signed quads.
- * ??? if -1/2 should produce -1 on this machine, this code is wrong
- */
-quad_t
-__divdi3(quad_t a, quad_t b)
-{
- u_quad_t ua, ub, uq;
- int neg;
-
- if (a < 0)
- ua = -(u_quad_t)a, neg = 1;
- else
- ua = a, neg = 0;
- if (b < 0)
- ub = -(u_quad_t)b, neg ^= 1;
- else
- ub = b;
- uq = __qdivrem(ua, ub, (u_quad_t *)0);
- return (neg ? -uq : uq);
-}
-
-/*
- * From
- * udivdi3.c
- */
-
-/*
- * Divide two unsigned quads.
- */
-u_quad_t
-__udivdi3(u_quad_t a, u_quad_t b)
-{
- return (__qdivrem(a, b, (u_quad_t *)0));
-}
-
-/*
- * From
- * umoddi3.c
- */
-
-/*
- * Return remainder after dividing two unsigned quads.
- */
-u_quad_t
-__umoddi3(u_quad_t a, u_quad_t b)
-{
- u_quad_t r;
-
- (void)__qdivrem(a, b, &r);
- return (r);
-}
-
-/*
- * From
- * moddi3.c
- */
-
-/*
- * Return remainder after dividing two signed quads.
- *
- * XXX
- * If -1/2 should produce -1 on this machine, this code is wrong.
- */
-quad_t
-__moddi3(quad_t a, quad_t b)
-{
- u_quad_t ua, ub, ur;
- int neg;
-
- if (a < 0)
- ua = -(u_quad_t)a, neg = 1;
- else
- ua = a, neg = 0;
- if (b < 0)
- ub = -(u_quad_t)b;
- else
- ub = b;
- (void)__qdivrem(ua, ub, &ur);
- return (neg ? -ur : ur);
-}
+++ /dev/null
-/*
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
- *
- * File: printf.c
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes: Grzegorz Milos (gm281@cam.ac.uk)
- *
- * Date: Aug 2003, Aug 2005
- *
- * Environment: Xen Minimal OS
- * Description: Library functions for printing
- * (Linux port, mainly lib/vsprintf.c)
- *
- ****************************************************************************
- */
-
-/*
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
-/*
- * Wirzenius wrote this portably, Torvalds fucked it up :-)
- */
-
-/*
- * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
- * - changed to provide snprintf and vsnprintf functions
- * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
- * - scnprintf and vscnprintf
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#if !defined HAVE_LIBC
-
-#include <mini-os/os.h>
-#include <mini-os/types.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/lib.h>
-#include <mini-os/mm.h>
-#include <mini-os/ctype.h>
-#include <mini-os/posix/limits.h>
-
-/**
- * simple_strtoul - convert a string to an unsigned long
- * @cp: The start of the string
- * @endp: A pointer to the end of the parsed string will be placed here
- * @base: The number base to use
- */
-unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
-{
- unsigned long result = 0,value;
-
- if (!base) {
- base = 10;
- if (*cp == '0') {
- base = 8;
- cp++;
- if ((*cp == 'x') && isxdigit(cp[1])) {
- cp++;
- base = 16;
- }
- }
- }
- while (isxdigit(*cp) &&
- (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
- result = result*base + value;
- cp++;
- }
- if (endp)
- *endp = (char *)cp;
- return result;
-}
-
-/**
- * simple_strtol - convert a string to a signed long
- * @cp: The start of the string
- * @endp: A pointer to the end of the parsed string will be placed here
- * @base: The number base to use
- */
-long simple_strtol(const char *cp,char **endp,unsigned int base)
-{
- if(*cp=='-')
- return -simple_strtoul(cp+1,endp,base);
- return simple_strtoul(cp,endp,base);
-}
-
-/**
- * simple_strtoull - convert a string to an unsigned long long
- * @cp: The start of the string
- * @endp: A pointer to the end of the parsed string will be placed here
- * @base: The number base to use
- */
-unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
-{
- unsigned long long result = 0,value;
-
- if (!base) {
- base = 10;
- if (*cp == '0') {
- base = 8;
- cp++;
- if ((*cp == 'x') && isxdigit(cp[1])) {
- cp++;
- base = 16;
- }
- }
- }
- while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
- ? toupper(*cp) : *cp)-'A'+10) < base) {
- result = result*base + value;
- cp++;
- }
- if (endp)
- *endp = (char *)cp;
- return result;
-}
-
-/**
- * simple_strtoll - convert a string to a signed long long
- * @cp: The start of the string
- * @endp: A pointer to the end of the parsed string will be placed here
- * @base: The number base to use
- */
-long long simple_strtoll(const char *cp,char **endp,unsigned int base)
-{
- if(*cp=='-')
- return -simple_strtoull(cp+1,endp,base);
- return simple_strtoull(cp,endp,base);
-}
-
-static int skip_atoi(const char **s)
-{
- int i=0;
-
- while (isdigit(**s))
- i = i*10 + *((*s)++) - '0';
- return i;
-}
-
-#define ZEROPAD 1 /* pad with zero */
-#define SIGN 2 /* unsigned/signed long */
-#define PLUS 4 /* show plus */
-#define SPACE 8 /* space if plus */
-#define LEFT 16 /* left justified */
-#define SPECIAL 32 /* 0x */
-#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
-
-static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
-{
- char c,sign,tmp[66];
- const char *digits;
- const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
- const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- int i;
-
- digits = (type & LARGE) ? large_digits : small_digits;
- if (type & LEFT)
- type &= ~ZEROPAD;
- if (base < 2 || base > 36)
- return buf;
- c = (type & ZEROPAD) ? '0' : ' ';
- sign = 0;
- if (type & SIGN) {
- if (num < 0) {
- sign = '-';
- num = -num;
- size--;
- } else if (type & PLUS) {
- sign = '+';
- size--;
- } else if (type & SPACE) {
- sign = ' ';
- size--;
- }
- }
- if (type & SPECIAL) {
- if (base == 16)
- size -= 2;
- else if (base == 8)
- size--;
- }
- i = 0;
- if (num == 0)
- tmp[i++]='0';
- else
- {
- /* XXX KAF: force unsigned mod and div. */
- unsigned long long num2=(unsigned long long)num;
- unsigned int base2=(unsigned int)base;
- while (num2 != 0) { tmp[i++] = digits[num2%base2]; num2 /= base2; }
- }
- if (i > precision)
- precision = i;
- size -= precision;
- if (!(type&(ZEROPAD+LEFT))) {
- while(size-->0) {
- if (buf <= end)
- *buf = ' ';
- ++buf;
- }
- }
- if (sign) {
- if (buf <= end)
- *buf = sign;
- ++buf;
- }
- if (type & SPECIAL) {
- if (base==8) {
- if (buf <= end)
- *buf = '0';
- ++buf;
- } else if (base==16) {
- if (buf <= end)
- *buf = '0';
- ++buf;
- if (buf <= end)
- *buf = digits[33];
- ++buf;
- }
- }
- if (!(type & LEFT)) {
- while (size-- > 0) {
- if (buf <= end)
- *buf = c;
- ++buf;
- }
- }
- while (i < precision--) {
- if (buf <= end)
- *buf = '0';
- ++buf;
- }
- while (i-- > 0) {
- if (buf <= end)
- *buf = tmp[i];
- ++buf;
- }
- while (size-- > 0) {
- if (buf <= end)
- *buf = ' ';
- ++buf;
- }
- return buf;
-}
-
-/**
-* vsnprintf - Format a string and place it in a buffer
-* @buf: The buffer to place the result into
-* @size: The size of the buffer, including the trailing null space
-* @fmt: The format string to use
-* @args: Arguments for the format string
-*
-* Call this function if you are already dealing with a va_list.
-* You probably want snprintf instead.
- */
-int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
-{
- int len;
- unsigned long long num;
- int i, base;
- char *str, *end, c;
- const char *s;
-
- int flags; /* flags to number() */
-
- int field_width; /* width of output field */
- int precision; /* min. # of digits for integers; max
- number of chars for from string */
- int qualifier; /* 'h', 'l', or 'L' for integer fields */
- /* 'z' support added 23/7/1999 S.H. */
- /* 'z' changed to 'Z' --davidm 1/25/99 */
-
- str = buf;
- end = buf + size - 1;
-
- if (end < buf - 1) {
- end = ((void *) -1);
- size = end - buf + 1;
- }
-
- for (; *fmt ; ++fmt) {
- if (*fmt != '%') {
- if (str <= end)
- *str = *fmt;
- ++str;
- continue;
- }
-
- /* process flags */
- flags = 0;
- repeat:
- ++fmt; /* this also skips first '%' */
- switch (*fmt) {
- case '-': flags |= LEFT; goto repeat;
- case '+': flags |= PLUS; goto repeat;
- case ' ': flags |= SPACE; goto repeat;
- case '#': flags |= SPECIAL; goto repeat;
- case '0': flags |= ZEROPAD; goto repeat;
- }
-
- /* get field width */
- field_width = -1;
- if (isdigit(*fmt))
- field_width = skip_atoi(&fmt);
- else if (*fmt == '*') {
- ++fmt;
- /* it's the next argument */
- field_width = va_arg(args, int);
- if (field_width < 0) {
- field_width = -field_width;
- flags |= LEFT;
- }
- }
-
- /* get the precision */
- precision = -1;
- if (*fmt == '.') {
- ++fmt;
- if (isdigit(*fmt))
- precision = skip_atoi(&fmt);
- else if (*fmt == '*') {
- ++fmt;
- /* it's the next argument */
- precision = va_arg(args, int);
- }
- if (precision < 0)
- precision = 0;
- }
-
- /* get the conversion qualifier */
- qualifier = -1;
- if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
- qualifier = *fmt;
- ++fmt;
- if (qualifier == 'l' && *fmt == 'l') {
- qualifier = 'L';
- ++fmt;
- }
- }
- if (*fmt == 'q') {
- qualifier = 'L';
- ++fmt;
- }
-
- /* default base */
- base = 10;
-
- switch (*fmt) {
- case 'c':
- if (!(flags & LEFT)) {
- while (--field_width > 0) {
- if (str <= end)
- *str = ' ';
- ++str;
- }
- }
- c = (unsigned char) va_arg(args, int);
- if (str <= end)
- *str = c;
- ++str;
- while (--field_width > 0) {
- if (str <= end)
- *str = ' ';
- ++str;
- }
- continue;
-
- case 's':
- s = va_arg(args, char *);
- if (!s)
- s = "<NULL>";
-
- len = strnlen(s, precision);
-
- if (!(flags & LEFT)) {
- while (len < field_width--) {
- if (str <= end)
- *str = ' ';
- ++str;
- }
- }
- for (i = 0; i < len; ++i) {
- if (str <= end)
- *str = *s;
- ++str; ++s;
- }
- while (len < field_width--) {
- if (str <= end)
- *str = ' ';
- ++str;
- }
- continue;
-
- case 'p':
- if (field_width == -1) {
- field_width = 2*sizeof(void *);
- flags |= ZEROPAD;
- }
- str = number(str, end,
- (unsigned long) va_arg(args, void *),
- 16, field_width, precision, flags);
- continue;
-
-
- case 'n':
- if (qualifier == 'l') {
- long * ip = va_arg(args, long *);
- *ip = (str - buf);
- } else if (qualifier == 'Z') {
- size_t * ip = va_arg(args, size_t *);
- *ip = (str - buf);
- } else {
- int * ip = va_arg(args, int *);
- *ip = (str - buf);
- }
- continue;
-
- case '%':
- if (str <= end)
- *str = '%';
- ++str;
- continue;
-
- /* integer number formats - set up the flags and "break" */
- case 'o':
- base = 8;
- break;
-
- case 'X':
- flags |= LARGE;
- case 'x':
- base = 16;
- break;
-
- case 'd':
- case 'i':
- flags |= SIGN;
- case 'u':
- break;
-
- default:
- if (str <= end)
- *str = '%';
- ++str;
- if (*fmt) {
- if (str <= end)
- *str = *fmt;
- ++str;
- } else {
- --fmt;
- }
- continue;
- }
- if (qualifier == 'L')
- num = va_arg(args, long long);
- else if (qualifier == 'l') {
- num = va_arg(args, unsigned long);
- if (flags & SIGN)
- num = (signed long) num;
- } else if (qualifier == 'Z') {
- num = va_arg(args, size_t);
- } else if (qualifier == 'h') {
- num = (unsigned short) va_arg(args, int);
- if (flags & SIGN)
- num = (signed short) num;
- } else {
- num = va_arg(args, unsigned int);
- if (flags & SIGN)
- num = (signed int) num;
- }
-
- str = number(str, end, num, base,
- field_width, precision, flags);
- }
- if (str <= end)
- *str = '\0';
- else if (size > 0)
- /* don't write out a null byte if the buf size is zero */
- *end = '\0';
- /* the trailing null byte doesn't count towards the total
- * ++str;
- */
- return str-buf;
-}
-
-/**
- * snprintf - Format a string and place it in a buffer
- * @buf: The buffer to place the result into
- * @size: The size of the buffer, including the trailing null space
- * @fmt: The format string to use
- * @...: Arguments for the format string
- */
-int snprintf(char * buf, size_t size, const char *fmt, ...)
-{
- va_list args;
- int i;
-
- va_start(args, fmt);
- i=vsnprintf(buf,size,fmt,args);
- va_end(args);
- return i;
-}
-
-/**
- * vsprintf - Format a string and place it in a buffer
- * @buf: The buffer to place the result into
- * @fmt: The format string to use
- * @args: Arguments for the format string
- *
- * Call this function if you are already dealing with a va_list.
- * You probably want sprintf instead.
- */
-int vsprintf(char *buf, const char *fmt, va_list args)
-{
- return vsnprintf(buf, 0xFFFFFFFFUL, fmt, args);
-}
-
-
-/**
- * sprintf - Format a string and place it in a buffer
- * @buf: The buffer to place the result into
- * @fmt: The format string to use
- * @...: Arguments for the format string
- */
-int sprintf(char * buf, const char *fmt, ...)
-{
- va_list args;
- int i;
-
- va_start(args, fmt);
- i=vsprintf(buf,fmt,args);
- va_end(args);
- return i;
-}
-
-/**
- * vsscanf - Unformat a buffer into a list of arguments
- * @buf: input buffer
- * @fmt: format of buffer
- * @args: arguments
- */
-int vsscanf(const char * buf, const char * fmt, va_list args)
-{
- const char *str = buf;
- char *next;
- char digit;
- int num = 0;
- int qualifier;
- int base;
- int field_width;
- int is_sign = 0;
-
- while(*fmt && *str) {
- /* skip any white space in format */
- /* white space in format matchs any amount of
- * white space, including none, in the input.
- */
- if (isspace(*fmt)) {
- while (isspace(*fmt))
- ++fmt;
- while (isspace(*str))
- ++str;
- }
-
- /* anything that is not a conversion must match exactly */
- if (*fmt != '%' && *fmt) {
- if (*fmt++ != *str++)
- break;
- continue;
- }
-
- if (!*fmt)
- break;
- ++fmt;
-
- /* skip this conversion.
- * advance both strings to next white space
- */
- if (*fmt == '*') {
- while (!isspace(*fmt) && *fmt)
- fmt++;
- while (!isspace(*str) && *str)
- str++;
- continue;
- }
-
- /* get field width */
- field_width = -1;
- if (isdigit(*fmt))
- field_width = skip_atoi(&fmt);
-
- /* get conversion qualifier */
- qualifier = -1;
- if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
- *fmt == 'Z' || *fmt == 'z') {
- qualifier = *fmt++;
- if (unlikely(qualifier == *fmt)) {
- if (qualifier == 'h') {
- qualifier = 'H';
- fmt++;
- } else if (qualifier == 'l') {
- qualifier = 'L';
- fmt++;
- }
- }
- }
- base = 10;
- is_sign = 0;
-
- if (!*fmt || !*str)
- break;
-
- switch(*fmt++) {
- case 'c':
- {
- char *s = (char *) va_arg(args,char*);
- if (field_width == -1)
- field_width = 1;
- do {
- *s++ = *str++;
- } while (--field_width > 0 && *str);
- num++;
- }
- continue;
- case 's':
- {
- char *s = (char *) va_arg(args, char *);
- if(field_width == -1)
- field_width = INT_MAX;
- /* first, skip leading white space in buffer */
- while (isspace(*str))
- str++;
-
- /* now copy until next white space */
- while (*str && !isspace(*str) && field_width--) {
- *s++ = *str++;
- }
- *s = '\0';
- num++;
- }
- continue;
- case 'n':
- /* return number of characters read so far */
- {
- int *i = (int *)va_arg(args,int*);
- *i = str - buf;
- }
- continue;
- case 'o':
- base = 8;
- break;
- case 'x':
- case 'X':
- base = 16;
- break;
- case 'i':
- base = 0;
- case 'd':
- is_sign = 1;
- case 'u':
- break;
- case '%':
- /* looking for '%' in str */
- if (*str++ != '%')
- return num;
- continue;
- default:
- /* invalid format; stop here */
- return num;
- }
-
- /* have some sort of integer conversion.
- * first, skip white space in buffer.
- */
- while (isspace(*str))
- str++;
-
- digit = *str;
- if (is_sign && digit == '-')
- digit = *(str + 1);
-
- if (!digit
- || (base == 16 && !isxdigit(digit))
- || (base == 10 && !isdigit(digit))
- || (base == 8 && (!isdigit(digit) || digit > '7'))
- || (base == 0 && !isdigit(digit)))
- break;
-
- switch(qualifier) {
- case 'H': /* that's 'hh' in format */
- if (is_sign) {
- signed char *s = (signed char *) va_arg(args,signed char *);
- *s = (signed char) simple_strtol(str,&next,base);
- } else {
- unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
- *s = (unsigned char) simple_strtoul(str, &next, base);
- }
- break;
- case 'h':
- if (is_sign) {
- short *s = (short *) va_arg(args,short *);
- *s = (short) simple_strtol(str,&next,base);
- } else {
- unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
- *s = (unsigned short) simple_strtoul(str, &next, base);
- }
- break;
- case 'l':
- if (is_sign) {
- long *l = (long *) va_arg(args,long *);
- *l = simple_strtol(str,&next,base);
- } else {
- unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
- *l = simple_strtoul(str,&next,base);
- }
- break;
- case 'L':
- if (is_sign) {
- long long *l = (long long*) va_arg(args,long long *);
- *l = simple_strtoll(str,&next,base);
- } else {
- unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
- *l = simple_strtoull(str,&next,base);
- }
- break;
- case 'Z':
- case 'z':
- {
- size_t *s = (size_t*) va_arg(args,size_t*);
- *s = (size_t) simple_strtoul(str,&next,base);
- }
- break;
- default:
- if (is_sign) {
- int *i = (int *) va_arg(args, int*);
- *i = (int) simple_strtol(str,&next,base);
- } else {
- unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
- *i = (unsigned int) simple_strtoul(str,&next,base);
- }
- break;
- }
- num++;
-
- if (!next)
- break;
- str = next;
- }
- return num;
-}
-
-/**
- * sscanf - Unformat a buffer into a list of arguments
- * @buf: input buffer
- * @fmt: formatting of buffer
- * @...: resulting arguments
- */
-int sscanf(const char * buf, const char * fmt, ...)
-{
- va_list args;
- int i;
-
- va_start(args,fmt);
- i = vsscanf(buf,fmt,args);
- va_end(args);
- return i;
-}
-
-#endif
+++ /dev/null
-#include <mini-os/kernel.h>
-#include <mini-os/console.h>
-
-void __stack_chk_fail(void)
-{
- printk("stack smashing detected\n");
- do_exit();
-}
+++ /dev/null
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
- *
- * File: string.c
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes:
- *
- * Date: Aug 2003
- *
- * Environment: Xen Minimal OS
- * Description: Library function for string and memory manipulation
- * Origin unknown
- *
- ****************************************************************************
- * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
- ****************************************************************************
- */
-
-#include <strings.h>
-
-/* newlib defines ffs but not ffsll or ffsl */
-int __ffsti2 (long long int lli)
-{
- int i, num, t, tmpint, len;
-
- num = sizeof(long long int) / sizeof(int);
- if (num == 1) return (ffs((int) lli));
- len = sizeof(int) * 8;
-
- for (i = 0; i < num; i++) {
- tmpint = (int) (((lli >> len) << len) ^ lli);
-
- t = ffs(tmpint);
- if (t)
- return (t + i * len);
- lli = lli >> len;
- }
- return 0;
-}
-
-int __ffsdi2 (long int li)
-{
- return __ffsti2 ((long long int) li);
-}
-
-int ffsl (long int li)
-{
- return __ffsti2 ((long long int) li);
-}
-
-int ffsll (long long int lli)
-{
- return __ffsti2 (lli);
-}
-
-#if !defined HAVE_LIBC
-
-#include <mini-os/os.h>
-#include <mini-os/types.h>
-#include <mini-os/lib.h>
-#include <mini-os/xmalloc.h>
-
-int memcmp(const void * cs,const void * ct,size_t count)
-{
- const unsigned char *su1, *su2;
- signed char res = 0;
-
- for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
- if ((res = *su1 - *su2) != 0)
- break;
- return res;
-}
-
-void * memcpy(void * dest,const void *src,size_t count)
-{
- char *tmp = (char *) dest;
- const char *s = src;
-
- while (count--)
- *tmp++ = *s++;
-
- return dest;
-}
-
-int strncmp(const char * cs,const char * ct,size_t count)
-{
- register signed char __res = 0;
-
- while (count) {
- if ((__res = *cs - *ct++) != 0 || !*cs++)
- break;
- count--;
- }
-
- return __res;
-}
-
-int strcmp(const char * cs,const char * ct)
-{
- register signed char __res;
-
- while (1) {
- if ((__res = *cs - *ct++) != 0 || !*cs++)
- break;
- }
-
- return __res;
-}
-
-char * strcpy(char * dest,const char *src)
-{
- char *tmp = dest;
-
- while ((*dest++ = *src++) != '\0')
- /* nothing */;
- return tmp;
-}
-
-char * strncpy(char * dest,const char *src,size_t count)
-{
- char *tmp = dest;
-
- while (count-- && (*dest++ = *src++) != '\0')
- /* nothing */;
-
- return tmp;
-}
-
-void * memset(void * s,int c,size_t count)
-{
- char *xs = (char *) s;
-
- while (count--)
- *xs++ = c;
-
- return s;
-}
-
-size_t strnlen(const char * s, size_t count)
-{
- const char *sc;
-
- for (sc = s; count-- && *sc != '\0'; ++sc)
- /* nothing */;
- return sc - s;
-}
-
-
-char * strcat(char * dest, const char * src)
-{
- char *tmp = dest;
-
- while (*dest)
- dest++;
-
- while ((*dest++ = *src++) != '\0');
-
- return tmp;
-}
-
-size_t strlen(const char * s)
-{
- const char *sc;
-
- for (sc = s; *sc != '\0'; ++sc)
- /* nothing */;
- return sc - s;
-}
-
-char * strchr(const char * s, int c)
-{
- for(; *s != (char) c; ++s)
- if (*s == '\0')
- return NULL;
- return (char *)s;
-}
-
-char * strrchr(const char * s, int c)
-{
- const char *res = NULL;
- for(; *s != '\0'; ++s)
- if (*s == (char) c)
- res = s;
- return (char *)res;
-}
-
-char * strstr(const char * s1,const char * s2)
-{
- int l1, l2;
-
- l2 = strlen(s2);
- if (!l2)
- return (char *) s1;
- l1 = strlen(s1);
- while (l1 >= l2) {
- l1--;
- if (!memcmp(s1,s2,l2))
- return (char *) s1;
- s1++;
- }
- return NULL;
-}
-
-char *strdup(const char *x)
-{
- int l = strlen(x);
- char *res = malloc(l + 1);
- if (!res) return NULL;
- memcpy(res, x, l + 1);
- return res;
-}
-
-int ffs(int i)
-{
- int c = 1;
-
- do {
- if (i & 1)
- return (c);
- i = i >> 1;
- c++;
- } while (i);
- return 0;
-}
-
-#endif
+++ /dev/null
-/*
- * POSIX-compatible libc layer
- *
- * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, October 2007
- *
- * Provides the UNIXish part of the standard libc function.
- *
- * Relatively straight-forward: just multiplex the file descriptor operations
- * among the various file types (console, FS, network, ...)
- */
-
-//#define LIBC_VERBOSE
-//#define LIBC_DEBUG
-
-#ifdef LIBC_DEBUG
-#define DEBUG(fmt,...) printk(fmt, ##__VA_ARGS__)
-#else
-#define DEBUG(fmt,...)
-#endif
-
-#ifdef HAVE_LIBC
-#include <os.h>
-#include <console.h>
-#include <sched.h>
-#include <events.h>
-#include <wait.h>
-#include <netfront.h>
-#include <blkfront.h>
-#include <fbfront.h>
-#include <tpmfront.h>
-#include <tpm_tis.h>
-#include <xenbus.h>
-#include <xenstore.h>
-#include <poll.h>
-
-#include <sys/types.h>
-#include <sys/unistd.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <net/if.h>
-#include <time.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <assert.h>
-#include <dirent.h>
-#include <stdlib.h>
-#include <math.h>
-
-#ifdef HAVE_LWIP
-#include <lwip/sockets.h>
-#endif
-
-#define debug(fmt, ...) \
-
-#define print_unsupported(fmt, ...) \
- printk("Unsupported function "fmt" called in Mini-OS kernel\n", ## __VA_ARGS__);
-
-/* Crash on function call */
-#define unsupported_function_crash(function) \
- int __unsup_##function(void) asm(#function); \
- int __unsup_##function(void) \
- { \
- print_unsupported(#function); \
- do_exit(); \
- }
-
-/* Log and err out on function call */
-#define unsupported_function_log(type, function, ret) \
- type __unsup_##function(void) asm(#function); \
- type __unsup_##function(void) \
- { \
- print_unsupported(#function); \
- errno = ENOSYS; \
- return ret; \
- }
-
-/* Err out on function call */
-#define unsupported_function(type, function, ret) \
- type __unsup_##function(void) asm(#function); \
- type __unsup_##function(void) \
- { \
- errno = ENOSYS; \
- return ret; \
- }
-
-#define NOFILE 32
-extern void minios_interface_close_fd(int fd);
-extern void minios_evtchn_close_fd(int fd);
-extern void minios_gnttab_close_fd(int fd);
-
-pthread_mutex_t fd_lock = PTHREAD_MUTEX_INITIALIZER;
-struct file files[NOFILE] = {
- { .type = FTYPE_CONSOLE }, /* stdin */
- { .type = FTYPE_CONSOLE }, /* stdout */
- { .type = FTYPE_CONSOLE }, /* stderr */
-};
-
-DECLARE_WAIT_QUEUE_HEAD(event_queue);
-
-int alloc_fd(enum fd_type type)
-{
- int i;
- pthread_mutex_lock(&fd_lock);
- for (i=0; i<NOFILE; i++) {
- if (files[i].type == FTYPE_NONE) {
- files[i].type = type;
- pthread_mutex_unlock(&fd_lock);
- return i;
- }
- }
- pthread_mutex_unlock(&fd_lock);
- printk("Too many opened files\n");
- do_exit();
-}
-
-void close_all_files(void)
-{
- int i;
- pthread_mutex_lock(&fd_lock);
- for (i=NOFILE - 1; i > 0; i--)
- if (files[i].type != FTYPE_NONE)
- close(i);
- pthread_mutex_unlock(&fd_lock);
-}
-
-int dup2(int oldfd, int newfd)
-{
- pthread_mutex_lock(&fd_lock);
- if (files[newfd].type != FTYPE_NONE)
- close(newfd);
- // XXX: this is a bit bogus, as we are supposed to share the offset etc
- files[newfd] = files[oldfd];
- pthread_mutex_unlock(&fd_lock);
- return 0;
-}
-
-pid_t getpid(void)
-{
- return 1;
-}
-
-pid_t getppid(void)
-{
- return 1;
-}
-
-pid_t setsid(void)
-{
- return 1;
-}
-
-char *getcwd(char *buf, size_t size)
-{
- snprintf(buf, size, "/");
- return buf;
-}
-
-#define LOG_PATH "/var/log/"
-#define SAVE_PATH "/var/lib/xen"
-#define SAVE_CONSOLE 1
-#define RESTORE_CONSOLE 2
-
-int mkdir(const char *pathname, mode_t mode)
-{
- errno = EIO;
- return -1;
-}
-
-#ifdef CONFIG_CONSFRONT
-int posix_openpt(int flags)
-{
- struct consfront_dev *dev;
-
- /* Ignore flags */
-
- dev = init_consfront(NULL);
- dev->fd = alloc_fd(FTYPE_CONSOLE);
- files[dev->fd].cons.dev = dev;
-
- printk("fd(%d) = posix_openpt\n", dev->fd);
- return(dev->fd);
-}
-
-int open_savefile(const char *path, int save)
-{
- struct consfront_dev *dev;
- char nodename[64];
-
- snprintf(nodename, sizeof(nodename), "device/console/%d", save ? SAVE_CONSOLE : RESTORE_CONSOLE);
-
- dev = init_consfront(nodename);
- dev->fd = alloc_fd(FTYPE_SAVEFILE);
- files[dev->fd].cons.dev = dev;
-
- printk("fd(%d) = open_savefile\n", dev->fd);
- return(dev->fd);
-}
-#else
-int posix_openpt(int flags)
-{
- errno = EIO;
- return -1;
-}
-int open_savefile(const char *path, int save)
-{
- errno = EIO;
- return -1;
-}
-#endif
-
-int open(const char *pathname, int flags, ...)
-{
- int fd;
- /* Ugly, but fine. */
- if (!strncmp(pathname,LOG_PATH,strlen(LOG_PATH))) {
- fd = alloc_fd(FTYPE_CONSOLE);
- printk("open(%s) -> %d\n", pathname, fd);
- return fd;
- }
- if (!strncmp(pathname, "/dev/mem", strlen("/dev/mem"))) {
- fd = alloc_fd(FTYPE_MEM);
- printk("open(/dev/mem) -> %d\n", fd);
- return fd;
- }
- if (!strncmp(pathname, "/dev/ptmx", strlen("/dev/ptmx")))
- return posix_openpt(flags);
- if (!strncmp(pathname,SAVE_PATH,strlen(SAVE_PATH)))
- return open_savefile(pathname, flags & O_WRONLY);
- errno = EIO;
- return -1;
-}
-
-int isatty(int fd)
-{
- return files[fd].type == FTYPE_CONSOLE;
-}
-
-int read(int fd, void *buf, size_t nbytes)
-{
- switch (files[fd].type) {
- case FTYPE_SAVEFILE:
- case FTYPE_CONSOLE: {
- int ret;
- DEFINE_WAIT(w);
- while(1) {
- add_waiter(w, console_queue);
- ret = xencons_ring_recv(files[fd].cons.dev, buf, nbytes);
- if (ret)
- break;
- schedule();
- }
- remove_waiter(w, console_queue);
- return ret;
- }
-#ifdef HAVE_LWIP
- case FTYPE_SOCKET:
- return lwip_read(files[fd].socket.fd, buf, nbytes);
-#endif
-#ifdef CONFIG_NETFRONT
- case FTYPE_TAP: {
- ssize_t ret;
- ret = netfront_receive(files[fd].tap.dev, buf, nbytes);
- if (ret <= 0) {
- errno = EAGAIN;
- return -1;
- }
- return ret;
- }
-#endif
-#ifdef CONFIG_KBDFRONT
- case FTYPE_KBD: {
- int ret, n;
- n = nbytes / sizeof(union xenkbd_in_event);
- ret = kbdfront_receive(files[fd].kbd.dev, buf, n);
- if (ret <= 0) {
- errno = EAGAIN;
- return -1;
- }
- return ret * sizeof(union xenkbd_in_event);
- }
-#endif
-#ifdef CONFIG_FBFRONT
- case FTYPE_FB: {
- int ret, n;
- n = nbytes / sizeof(union xenfb_in_event);
- ret = fbfront_receive(files[fd].fb.dev, buf, n);
- if (ret <= 0) {
- errno = EAGAIN;
- return -1;
- }
- return ret * sizeof(union xenfb_in_event);
- }
-#endif
-#ifdef CONFIG_BLKFRONT
- case FTYPE_BLK: {
- return blkfront_posix_read(fd, buf, nbytes);
- }
-#endif
-#ifdef CONFIG_TPMFRONT
- case FTYPE_TPMFRONT: {
- return tpmfront_posix_read(fd, buf, nbytes);
- }
-#endif
-#ifdef CONFIG_TPM_TIS
- case FTYPE_TPM_TIS: {
- return tpm_tis_posix_read(fd, buf, nbytes);
- }
-#endif
- default:
- break;
- }
- printk("read(%d): Bad descriptor\n", fd);
- errno = EBADF;
- return -1;
-}
-
-int write(int fd, const void *buf, size_t nbytes)
-{
- switch (files[fd].type) {
- case FTYPE_SAVEFILE: {
- int ret = 0, tot = nbytes;
- while (nbytes > 0) {
- ret = xencons_ring_send(files[fd].cons.dev, (char *)buf, nbytes);
- nbytes -= ret;
- buf = (char *)buf + ret;
- }
- return tot - nbytes;
- }
- case FTYPE_CONSOLE:
- console_print(files[fd].cons.dev, (char *)buf, nbytes);
- return nbytes;
-#ifdef HAVE_LWIP
- case FTYPE_SOCKET:
- return lwip_write(files[fd].socket.fd, (void*) buf, nbytes);
-#endif
-#ifdef CONFIG_NETFRONT
- case FTYPE_TAP:
- netfront_xmit(files[fd].tap.dev, (void*) buf, nbytes);
- return nbytes;
-#endif
-#ifdef CONFIG_BLKFRONT
- case FTYPE_BLK:
- return blkfront_posix_write(fd, buf, nbytes);
-#endif
-#ifdef CONFIG_TPMFRONT
- case FTYPE_TPMFRONT:
- return tpmfront_posix_write(fd, buf, nbytes);
-#endif
-#ifdef CONFIG_TPM_TIS
- case FTYPE_TPM_TIS:
- return tpm_tis_posix_write(fd, buf, nbytes);
-#endif
- default:
- break;
- }
- printk("write(%d): Bad descriptor\n", fd);
- errno = EBADF;
- return -1;
-}
-
-off_t lseek(int fd, off_t offset, int whence)
-{
- off_t* target = NULL;
- switch(files[fd].type) {
-#ifdef CONFIG_BLKFRONT
- case FTYPE_BLK:
- target = &files[fd].blk.offset;
- break;
-#endif
-#ifdef CONFIG_TPMFRONT
- case FTYPE_TPMFRONT:
- target = &files[fd].tpmfront.offset;
- break;
-#endif
-#ifdef CONFIG_TPM_TIS
- case FTYPE_TPM_TIS:
- target = &files[fd].tpm_tis.offset;
- break;
-#endif
- case FTYPE_FILE:
- target = &files[fd].file.offset;
- break;
- default:
- /* Not implemented for this filetype */
- errno = ESPIPE;
- return (off_t) -1;
- }
-
- switch (whence) {
- case SEEK_SET:
- *target = offset;
- break;
- case SEEK_CUR:
- *target += offset;
- break;
- case SEEK_END:
- {
- struct stat st;
- int ret;
- ret = fstat(fd, &st);
- if (ret)
- return -1;
- *target = st.st_size + offset;
- break;
- }
- default:
- errno = EINVAL;
- return -1;
- }
- return *target;
-}
-
-int fsync(int fd) {
- errno = EBADF;
- return -1;
-}
-
-int close(int fd)
-{
- printk("close(%d)\n", fd);
- switch (files[fd].type) {
- default:
- files[fd].type = FTYPE_NONE;
- return 0;
-#ifdef CONFIG_XENBUS
- case FTYPE_XENBUS:
- xs_daemon_close((void*)(intptr_t) fd);
- return 0;
-#endif
-#ifdef HAVE_LWIP
- case FTYPE_SOCKET: {
- int res = lwip_close(files[fd].socket.fd);
- files[fd].type = FTYPE_NONE;
- return res;
- }
-#endif
-#ifdef CONFIG_XC
- case FTYPE_XC:
- minios_interface_close_fd(fd);
- return 0;
- case FTYPE_EVTCHN:
- minios_evtchn_close_fd(fd);
- return 0;
- case FTYPE_GNTMAP:
- minios_gnttab_close_fd(fd);
- return 0;
-#endif
-#ifdef CONFIG_NETFRONT
- case FTYPE_TAP:
- shutdown_netfront(files[fd].tap.dev);
- files[fd].type = FTYPE_NONE;
- return 0;
-#endif
-#ifdef CONFIG_BLKFRONT
- case FTYPE_BLK:
- shutdown_blkfront(files[fd].blk.dev);
- files[fd].type = FTYPE_NONE;
- return 0;
-#endif
-#ifdef CONFIG_TPMFRONT
- case FTYPE_TPMFRONT:
- shutdown_tpmfront(files[fd].tpmfront.dev);
- files[fd].type = FTYPE_NONE;
- return 0;
-#endif
-#ifdef CONFIG_TPM_TIS
- case FTYPE_TPM_TIS:
- shutdown_tpm_tis(files[fd].tpm_tis.dev);
- files[fd].type = FTYPE_NONE;
- return 0;
-#endif
-#ifdef CONFIG_KBDFRONT
- case FTYPE_KBD:
- shutdown_kbdfront(files[fd].kbd.dev);
- files[fd].type = FTYPE_NONE;
- return 0;
-#endif
-#ifdef CONFIG_FBFRONT
- case FTYPE_FB:
- shutdown_fbfront(files[fd].fb.dev);
- files[fd].type = FTYPE_NONE;
- return 0;
-#endif
-#ifdef CONFIG_CONSFRONT
- case FTYPE_SAVEFILE:
- case FTYPE_CONSOLE:
- fini_console(files[fd].cons.dev);
- files[fd].type = FTYPE_NONE;
- return 0;
-#endif
- case FTYPE_NONE:
- break;
- }
- printk("close(%d): Bad descriptor\n", fd);
- errno = EBADF;
- return -1;
-}
-
-static void init_stat(struct stat *buf)
-{
- memset(buf, 0, sizeof(*buf));
- buf->st_dev = 0;
- buf->st_ino = 0;
- buf->st_nlink = 1;
- buf->st_rdev = 0;
- buf->st_blksize = 4096;
- buf->st_blocks = 0;
-}
-
-int stat(const char *path, struct stat *buf)
-{
- errno = EIO;
- return -1;
-}
-
-int fstat(int fd, struct stat *buf)
-{
- init_stat(buf);
- switch (files[fd].type) {
- case FTYPE_SAVEFILE:
- case FTYPE_CONSOLE:
- case FTYPE_SOCKET: {
- if (files[fd].type == FTYPE_CONSOLE)
- buf->st_mode = S_IFCHR|S_IRUSR|S_IWUSR;
- else if (files[fd].type == FTYPE_SOCKET)
- buf->st_mode = S_IFSOCK|S_IRUSR|S_IWUSR;
- else if (files[fd].type == FTYPE_SAVEFILE)
- buf->st_mode = S_IFREG|S_IRUSR|S_IWUSR;
- buf->st_uid = 0;
- buf->st_gid = 0;
- buf->st_size = 0;
- buf->st_atime =
- buf->st_mtime =
- buf->st_ctime = time(NULL);
- return 0;
- }
-#ifdef CONFIG_BLKFRONT
- case FTYPE_BLK:
- return blkfront_posix_fstat(fd, buf);
-#endif
-#ifdef CONFIG_TPMFRONT
- case FTYPE_TPMFRONT:
- return tpmfront_posix_fstat(fd, buf);
-#endif
-#ifdef CONFIG_TPM_TIS
- case FTYPE_TPM_TIS:
- return tpm_tis_posix_fstat(fd, buf);
-#endif
- default:
- break;
- }
-
- printk("statf(%d): Bad descriptor\n", fd);
- errno = EBADF;
- return -1;
-}
-
-int ftruncate(int fd, off_t length)
-{
- errno = EBADF;
- return -1;
-}
-
-int remove(const char *pathname)
-{
- errno = EIO;
- return -1;
-}
-
-int unlink(const char *pathname)
-{
- return remove(pathname);
-}
-
-int rmdir(const char *pathname)
-{
- return remove(pathname);
-}
-
-int fcntl(int fd, int cmd, ...)
-{
- long arg;
- va_list ap;
- va_start(ap, cmd);
- arg = va_arg(ap, long);
- va_end(ap);
-
- switch (cmd) {
-#ifdef HAVE_LWIP
- case F_SETFL:
- if (files[fd].type == FTYPE_SOCKET && !(arg & ~O_NONBLOCK)) {
- /* Only flag supported: non-blocking mode */
- uint32_t nblock = !!(arg & O_NONBLOCK);
- return lwip_ioctl(files[fd].socket.fd, FIONBIO, &nblock);
- }
- /* Fallthrough */
-#endif
- default:
- printk("fcntl(%d, %d, %lx/%lo)\n", fd, cmd, arg, arg);
- errno = ENOSYS;
- return -1;
- }
-}
-
-DIR *opendir(const char *name)
-{
- DIR *ret;
- ret = malloc(sizeof(*ret));
- ret->name = strdup(name);
- ret->offset = 0;
- ret->entries = NULL;
- ret->curentry = -1;
- ret->nbentries = 0;
- ret->has_more = 1;
- return ret;
-}
-
-struct dirent *readdir(DIR *dir)
-{
- return NULL;
-}
-
-int closedir(DIR *dir)
-{
- int i;
- for (i=0; i<dir->nbentries; i++)
- free(dir->entries[i]);
- free(dir->entries);
- free(dir->name);
- free(dir);
- return 0;
-}
-
-/* We assume that only the main thread calls select(). */
-
-static const char file_types[] = {
- [FTYPE_NONE] = 'N',
- [FTYPE_CONSOLE] = 'C',
- [FTYPE_XENBUS] = 'S',
- [FTYPE_XC] = 'X',
- [FTYPE_EVTCHN] = 'E',
- [FTYPE_SOCKET] = 's',
- [FTYPE_TAP] = 'T',
- [FTYPE_BLK] = 'B',
- [FTYPE_KBD] = 'K',
- [FTYPE_FB] = 'G',
-};
-#ifdef LIBC_DEBUG
-static void dump_set(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
-{
- int i, comma;
-#define printfds(set) do {\
- comma = 0; \
- for (i = 0; i < nfds; i++) { \
- if (FD_ISSET(i, set)) { \
- if (comma) \
- printk(", "); \
- printk("%d(%c)", i, file_types[files[i].type]); \
- comma = 1; \
- } \
- } \
-} while (0)
-
- printk("[");
- if (readfds)
- printfds(readfds);
- printk("], [");
- if (writefds)
- printfds(writefds);
- printk("], [");
- if (exceptfds)
- printfds(exceptfds);
- printk("], ");
- if (timeout)
- printk("{ %ld, %ld }", timeout->tv_sec, timeout->tv_usec);
-}
-#else
-#define dump_set(nfds, readfds, writefds, exceptfds, timeout)
-#endif
-
-#ifdef LIBC_DEBUG
-static void dump_pollfds(struct pollfd *pfd, int nfds, int timeout)
-{
- int i, comma, fd;
-
- printk("[");
- comma = 0;
- for (i = 0; i < nfds; i++) {
- fd = pfd[i].fd;
- if (comma)
- printk(", ");
- printk("%d(%c)/%02x", fd, file_types[files[fd].type],
- pfd[i].events);
- comma = 1;
- }
- printk("]");
-
- printk(", %d, %d", nfds, timeout);
-}
-#else
-#define dump_pollfds(pfds, nfds, timeout)
-#endif
-
-/* Just poll without blocking */
-static int select_poll(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
-{
- int i, n = 0;
-#ifdef HAVE_LWIP
- int sock_n = 0, sock_nfds = 0;
- fd_set sock_readfds, sock_writefds, sock_exceptfds;
- struct timeval timeout = { .tv_sec = 0, .tv_usec = 0};
-#endif
-
-#ifdef LIBC_VERBOSE
- static int nb;
- static int nbread[NOFILE], nbwrite[NOFILE], nbexcept[NOFILE];
- static s_time_t lastshown;
-
- nb++;
-#endif
-
-#ifdef HAVE_LWIP
- /* first poll network */
- FD_ZERO(&sock_readfds);
- FD_ZERO(&sock_writefds);
- FD_ZERO(&sock_exceptfds);
- for (i = 0; i < nfds; i++) {
- if (files[i].type == FTYPE_SOCKET) {
- if (FD_ISSET(i, readfds)) {
- FD_SET(files[i].socket.fd, &sock_readfds);
- sock_nfds = i+1;
- }
- if (FD_ISSET(i, writefds)) {
- FD_SET(files[i].socket.fd, &sock_writefds);
- sock_nfds = i+1;
- }
- if (FD_ISSET(i, exceptfds)) {
- FD_SET(files[i].socket.fd, &sock_exceptfds);
- sock_nfds = i+1;
- }
- }
- }
- if (sock_nfds > 0) {
- DEBUG("lwip_select(");
- dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
- DEBUG("); -> ");
- sock_n = lwip_select(sock_nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
- dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
- DEBUG("\n");
- }
-#endif
-
- /* Then see others as well. */
- for (i = 0; i < nfds; i++) {
- switch(files[i].type) {
- default:
- if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
- printk("bogus fd %d in select\n", i);
- /* Fallthrough. */
- case FTYPE_CONSOLE:
- if (FD_ISSET(i, readfds)) {
- if (xencons_ring_avail(files[i].cons.dev))
- n++;
- else
- FD_CLR(i, readfds);
- }
- if (FD_ISSET(i, writefds))
- n++;
- FD_CLR(i, exceptfds);
- break;
-#ifdef CONFIG_XENBUS
- case FTYPE_XENBUS:
- if (FD_ISSET(i, readfds)) {
- if (files[i].xenbus.events)
- n++;
- else
- FD_CLR(i, readfds);
- }
- FD_CLR(i, writefds);
- FD_CLR(i, exceptfds);
- break;
-#endif
- case FTYPE_EVTCHN:
- case FTYPE_TAP:
- case FTYPE_BLK:
- case FTYPE_KBD:
- case FTYPE_FB:
- if (FD_ISSET(i, readfds)) {
- if (files[i].read)
- n++;
- else
- FD_CLR(i, readfds);
- }
- FD_CLR(i, writefds);
- FD_CLR(i, exceptfds);
- break;
-#ifdef HAVE_LWIP
- case FTYPE_SOCKET:
- if (FD_ISSET(i, readfds)) {
- /* Optimize no-network-packet case. */
- if (sock_n && FD_ISSET(files[i].socket.fd, &sock_readfds))
- n++;
- else
- FD_CLR(i, readfds);
- }
- if (FD_ISSET(i, writefds)) {
- if (sock_n && FD_ISSET(files[i].socket.fd, &sock_writefds))
- n++;
- else
- FD_CLR(i, writefds);
- }
- if (FD_ISSET(i, exceptfds)) {
- if (sock_n && FD_ISSET(files[i].socket.fd, &sock_exceptfds))
- n++;
- else
- FD_CLR(i, exceptfds);
- }
- break;
-#endif
- }
-#ifdef LIBC_VERBOSE
- if (FD_ISSET(i, readfds))
- nbread[i]++;
- if (FD_ISSET(i, writefds))
- nbwrite[i]++;
- if (FD_ISSET(i, exceptfds))
- nbexcept[i]++;
-#endif
- }
-#ifdef LIBC_VERBOSE
- if (NOW() > lastshown + 1000000000ull) {
- lastshown = NOW();
- printk("%lu MB free, ", num_free_pages() / ((1 << 20) / PAGE_SIZE));
- printk("%d(%d): ", nb, sock_n);
- for (i = 0; i < nfds; i++) {
- if (nbread[i] || nbwrite[i] || nbexcept[i])
- printk(" %d(%c):", i, file_types[files[i].type]);
- if (nbread[i])
- printk(" %dR", nbread[i]);
- if (nbwrite[i])
- printk(" %dW", nbwrite[i]);
- if (nbexcept[i])
- printk(" %dE", nbexcept[i]);
- }
- printk("\n");
- memset(nbread, 0, sizeof(nbread));
- memset(nbwrite, 0, sizeof(nbwrite));
- memset(nbexcept, 0, sizeof(nbexcept));
- nb = 0;
- }
-#endif
- return n;
-}
-
-/* The strategy is to
- * - announce that we will maybe sleep
- * - poll a bit ; if successful, return
- * - if timeout, return
- * - really sleep (except if somebody woke us in the meanwhile) */
-int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
- struct timeval *timeout)
-{
- int n, ret;
- fd_set myread, mywrite, myexcept;
- struct thread *thread = get_current();
- s_time_t start = NOW(), stop;
-#ifdef CONFIG_NETFRONT
- DEFINE_WAIT(netfront_w);
-#endif
- DEFINE_WAIT(event_w);
-#ifdef CONFIG_BLKFRONT
- DEFINE_WAIT(blkfront_w);
-#endif
-#ifdef CONFIG_XENBUS
- DEFINE_WAIT(xenbus_watch_w);
-#endif
-#ifdef CONFIG_KBDFRONT
- DEFINE_WAIT(kbdfront_w);
-#endif
- DEFINE_WAIT(console_w);
-
- assert(thread == main_thread);
-
- DEBUG("select(%d, ", nfds);
- dump_set(nfds, readfds, writefds, exceptfds, timeout);
- DEBUG(");\n");
-
- if (timeout)
- stop = start + SECONDS(timeout->tv_sec) + timeout->tv_usec * 1000;
- else
- /* just make gcc happy */
- stop = start;
-
- /* Tell people we're going to sleep before looking at what they are
- * saying, hence letting them wake us if events happen between here and
- * schedule() */
-#ifdef CONFIG_NETFRONT
- add_waiter(netfront_w, netfront_queue);
-#endif
- add_waiter(event_w, event_queue);
-#ifdef CONFIG_BLKFRONT
- add_waiter(blkfront_w, blkfront_queue);
-#endif
-#ifdef CONFIG_XENBUS
- add_waiter(xenbus_watch_w, xenbus_watch_queue);
-#endif
-#ifdef CONFIG_KBDFRONT
- add_waiter(kbdfront_w, kbdfront_queue);
-#endif
- add_waiter(console_w, console_queue);
-
- if (readfds)
- myread = *readfds;
- else
- FD_ZERO(&myread);
- if (writefds)
- mywrite = *writefds;
- else
- FD_ZERO(&mywrite);
- if (exceptfds)
- myexcept = *exceptfds;
- else
- FD_ZERO(&myexcept);
-
- DEBUG("polling ");
- dump_set(nfds, &myread, &mywrite, &myexcept, timeout);
- DEBUG("\n");
- n = select_poll(nfds, &myread, &mywrite, &myexcept);
-
- if (n) {
- dump_set(nfds, readfds, writefds, exceptfds, timeout);
- if (readfds)
- *readfds = myread;
- if (writefds)
- *writefds = mywrite;
- if (exceptfds)
- *exceptfds = myexcept;
- DEBUG(" -> ");
- dump_set(nfds, readfds, writefds, exceptfds, timeout);
- DEBUG("\n");
- wake(thread);
- ret = n;
- goto out;
- }
- if (timeout && NOW() >= stop) {
- if (readfds)
- FD_ZERO(readfds);
- if (writefds)
- FD_ZERO(writefds);
- if (exceptfds)
- FD_ZERO(exceptfds);
- timeout->tv_sec = 0;
- timeout->tv_usec = 0;
- wake(thread);
- ret = 0;
- goto out;
- }
-
- if (timeout)
- thread->wakeup_time = stop;
- schedule();
-
- if (readfds)
- myread = *readfds;
- else
- FD_ZERO(&myread);
- if (writefds)
- mywrite = *writefds;
- else
- FD_ZERO(&mywrite);
- if (exceptfds)
- myexcept = *exceptfds;
- else
- FD_ZERO(&myexcept);
-
- n = select_poll(nfds, &myread, &mywrite, &myexcept);
-
- if (n) {
- if (readfds)
- *readfds = myread;
- if (writefds)
- *writefds = mywrite;
- if (exceptfds)
- *exceptfds = myexcept;
- ret = n;
- goto out;
- }
- errno = EINTR;
- ret = -1;
-
-out:
-#ifdef CONFIG_NETFRONT
- remove_waiter(netfront_w, netfront_queue);
-#endif
- remove_waiter(event_w, event_queue);
-#ifdef CONFIG_BLKFRONT
- remove_waiter(blkfront_w, blkfront_queue);
-#endif
-#ifdef CONFIG_XENBUS
- remove_waiter(xenbus_watch_w, xenbus_watch_queue);
-#endif
-#ifdef CONFIG_KBDFRONT
- remove_waiter(kbdfront_w, kbdfront_queue);
-#endif
- remove_waiter(console_w, console_queue);
- return ret;
-}
-
-/* Wrap around select */
-int poll(struct pollfd _pfd[], nfds_t _nfds, int _timeout)
-{
- int n, ret;
- int i, fd;
- struct timeval _timeo, *timeo = NULL;
- fd_set rfds, wfds, efds;
- int max_fd = -1;
-
- DEBUG("poll(");
- dump_pollfds(_pfd, _nfds, _timeout);
- DEBUG(")\n");
-
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- FD_ZERO(&efds);
-
- n = 0;
-
- for (i = 0; i < _nfds; i++) {
- fd = _pfd[i].fd;
- _pfd[i].revents = 0;
-
- /* fd < 0, revents = 0, which is already set */
- if (fd < 0) continue;
-
- /* fd is invalid, revents = POLLNVAL, increment counter */
- if (fd >= NOFILE || files[fd].type == FTYPE_NONE) {
- n++;
- _pfd[i].revents |= POLLNVAL;
- continue;
- }
-
- /* normal case, map POLL* into readfds and writefds:
- * POLLIN -> readfds
- * POLLOUT -> writefds
- * POLL* -> none
- */
- if (_pfd[i].events & POLLIN)
- FD_SET(fd, &rfds);
- if (_pfd[i].events & POLLOUT)
- FD_SET(fd, &wfds);
- /* always set exceptfds */
- FD_SET(fd, &efds);
- if (fd > max_fd)
- max_fd = fd;
- }
-
- /* should never sleep when we already have events */
- if (n) {
- _timeo.tv_sec = 0;
- _timeo.tv_usec = 0;
- timeo = &_timeo;
- } else if (_timeout >= 0) {
- /* normal case, construct _timeout, might sleep */
- _timeo.tv_sec = _timeout / 1000;
- _timeo.tv_usec = (_timeout % 1000) * 1000;
- timeo = &_timeo;
- } else {
- /* _timeout < 0, block forever */
- timeo = NULL;
- }
-
-
- ret = select(max_fd+1, &rfds, &wfds, &efds, timeo);
- /* error in select, just return, errno is set by select() */
- if (ret < 0)
- return ret;
-
- for (i = 0; i < _nfds; i++) {
- fd = _pfd[i].fd;
-
- /* the revents has already been set for all error case */
- if (fd < 0 || fd >= NOFILE || files[fd].type == FTYPE_NONE)
- continue;
-
- if (FD_ISSET(fd, &rfds) || FD_ISSET(fd, &wfds) || FD_ISSET(fd, &efds))
- n++;
- if (FD_ISSET(fd, &efds)) {
- /* anything bad happens we set POLLERR */
- _pfd[i].revents |= POLLERR;
- continue;
- }
- if (FD_ISSET(fd, &rfds))
- _pfd[i].revents |= POLLIN;
- if (FD_ISSET(fd, &wfds))
- _pfd[i].revents |= POLLOUT;
- }
-
- return n;
-}
-
-#ifdef HAVE_LWIP
-int socket(int domain, int type, int protocol)
-{
- int fd, res;
- fd = lwip_socket(domain, type, protocol);
- if (fd < 0)
- return -1;
- res = alloc_fd(FTYPE_SOCKET);
- printk("socket -> %d\n", res);
- files[res].socket.fd = fd;
- return res;
-}
-
-int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
-{
- int fd, res;
- if (files[s].type != FTYPE_SOCKET) {
- printk("accept(%d): Bad descriptor\n", s);
- errno = EBADF;
- return -1;
- }
- fd = lwip_accept(files[s].socket.fd, addr, addrlen);
- if (fd < 0)
- return -1;
- res = alloc_fd(FTYPE_SOCKET);
- files[res].socket.fd = fd;
- printk("accepted on %d -> %d\n", s, res);
- return res;
-}
-
-#define LWIP_STUB(ret, name, proto, args) \
-ret name proto \
-{ \
- if (files[s].type != FTYPE_SOCKET) { \
- printk(#name "(%d): Bad descriptor\n", s); \
- errno = EBADF; \
- return -1; \
- } \
- s = files[s].socket.fd; \
- return lwip_##name args; \
-}
-
-LWIP_STUB(int, bind, (int s, struct sockaddr *my_addr, socklen_t addrlen), (s, my_addr, addrlen))
-LWIP_STUB(int, getsockopt, (int s, int level, int optname, void *optval, socklen_t *optlen), (s, level, optname, optval, optlen))
-LWIP_STUB(int, setsockopt, (int s, int level, int optname, void *optval, socklen_t optlen), (s, level, optname, optval, optlen))
-LWIP_STUB(int, connect, (int s, struct sockaddr *serv_addr, socklen_t addrlen), (s, serv_addr, addrlen))
-LWIP_STUB(int, listen, (int s, int backlog), (s, backlog));
-LWIP_STUB(ssize_t, recv, (int s, void *buf, size_t len, int flags), (s, buf, len, flags))
-LWIP_STUB(ssize_t, recvfrom, (int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen), (s, buf, len, flags, from, fromlen))
-LWIP_STUB(ssize_t, send, (int s, void *buf, size_t len, int flags), (s, buf, len, flags))
-LWIP_STUB(ssize_t, sendto, (int s, void *buf, size_t len, int flags, struct sockaddr *to, socklen_t tolen), (s, buf, len, flags, to, tolen))
-LWIP_STUB(int, getsockname, (int s, struct sockaddr *name, socklen_t *namelen), (s, name, namelen))
-#endif
-
-static char *syslog_ident;
-void openlog(const char *ident, int option, int facility)
-{
- free(syslog_ident);
- syslog_ident = strdup(ident);
-}
-
-void vsyslog(int priority, const char *format, va_list ap)
-{
- printk("%s: ", syslog_ident);
- print(0, format, ap);
-}
-
-void syslog(int priority, const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- vsyslog(priority, format, ap);
- va_end(ap);
-}
-
-void closelog(void)
-{
- free(syslog_ident);
- syslog_ident = NULL;
-}
-
-void vwarn(const char *format, va_list ap)
-{
- int the_errno = errno;
- printk("stubdom: ");
- if (format) {
- print(0, format, ap);
- printk(", ");
- }
- printk("%s", strerror(the_errno));
-}
-
-void warn(const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- vwarn(format, ap);
- va_end(ap);
-}
-
-void verr(int eval, const char *format, va_list ap)
-{
- vwarn(format, ap);
- exit(eval);
-}
-
-void err(int eval, const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- verr(eval, format, ap);
- va_end(ap);
-}
-
-void vwarnx(const char *format, va_list ap)
-{
- printk("stubdom: ");
- if (format)
- print(0, format, ap);
-}
-
-void warnx(const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- vwarnx(format, ap);
- va_end(ap);
-}
-
-void verrx(int eval, const char *format, va_list ap)
-{
- vwarnx(format, ap);
- exit(eval);
-}
-
-void errx(int eval, const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- verrx(eval, format, ap);
- va_end(ap);
-}
-
-int nanosleep(const struct timespec *req, struct timespec *rem)
-{
- s_time_t start = NOW();
- s_time_t stop = start + SECONDS(req->tv_sec) + req->tv_nsec;
- s_time_t stopped;
- struct thread *thread = get_current();
-
- thread->wakeup_time = stop;
- clear_runnable(thread);
- schedule();
- stopped = NOW();
-
- if (rem)
- {
- s_time_t remaining = stop - stopped;
- if (remaining > 0)
- {
- rem->tv_nsec = remaining % 1000000000ULL;
- rem->tv_sec = remaining / 1000000000ULL;
- } else memset(rem, 0, sizeof(*rem));
- }
-
- return 0;
-}
-
-int usleep(useconds_t usec)
-{
- /* "usec shall be less than one million." */
- struct timespec req;
- req.tv_nsec = usec * 1000;
- req.tv_sec = 0;
-
- if (nanosleep(&req, NULL))
- return -1;
-
- return 0;
-}
-
-unsigned int sleep(unsigned int seconds)
-{
- struct timespec req, rem;
- req.tv_sec = seconds;
- req.tv_nsec = 0;
-
- if (nanosleep(&req, &rem))
- return -1;
-
- if (rem.tv_nsec > 0)
- rem.tv_sec++;
-
- return rem.tv_sec;
-}
-
-int clock_gettime(clockid_t clk_id, struct timespec *tp)
-{
- switch (clk_id) {
- case CLOCK_MONOTONIC:
- {
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
-
- tp->tv_sec = tv.tv_sec;
- tp->tv_nsec = tv.tv_usec * 1000;
-
- break;
- }
- case CLOCK_REALTIME:
- {
- uint64_t nsec = monotonic_clock();
-
- tp->tv_sec = nsec / 1000000000ULL;
- tp->tv_nsec = nsec % 1000000000ULL;
-
- break;
- }
- default:
- print_unsupported("clock_gettime(%d)", clk_id);
- errno = EINVAL;
- return -1;
- }
-
- return 0;
-}
-
-uid_t getuid(void)
-{
- return 0;
-}
-
-uid_t geteuid(void)
-{
- return 0;
-}
-
-gid_t getgid(void)
-{
- return 0;
-}
-
-gid_t getegid(void)
-{
- return 0;
-}
-
-int gethostname(char *name, size_t namelen)
-{
- strncpy(name, "mini-os", namelen);
- return 0;
-}
-
-size_t getpagesize(void)
-{
- return PAGE_SIZE;
-}
-
-void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
-{
- unsigned long n = (length + PAGE_SIZE - 1) / PAGE_SIZE;
-
- ASSERT(!start);
- ASSERT(prot == (PROT_READ|PROT_WRITE));
- ASSERT((fd == -1 && (flags == (MAP_SHARED|MAP_ANON) || flags == (MAP_PRIVATE|MAP_ANON)))
- || (fd != -1 && flags == MAP_SHARED));
-
- if (fd == -1)
- return map_zero(n, 1);
-#ifdef CONFIG_XC
- else if (files[fd].type == FTYPE_XC) {
- unsigned long zero = 0;
- return map_frames_ex(&zero, n, 0, 0, 1, DOMID_SELF, NULL, 0);
- }
-#endif
- else if (files[fd].type == FTYPE_MEM) {
- unsigned long first_mfn = offset >> PAGE_SHIFT;
- return map_frames_ex(&first_mfn, n, 0, 1, 1, DOMID_IO, NULL, _PAGE_PRESENT|_PAGE_RW);
- } else ASSERT(0);
-}
-
-int munmap(void *start, size_t length)
-{
- int total = length / PAGE_SIZE;
- int ret;
-
- ret = unmap_frames((unsigned long)start, (unsigned long)total);
- if (ret) {
- errno = ret;
- return -1;
- }
- return 0;
-}
-
-void sparse(unsigned long data, size_t size)
-{
- unsigned long newdata;
- xen_pfn_t *mfns;
- int i, n;
-
- newdata = (data + PAGE_SIZE - 1) & PAGE_MASK;
- if (newdata - data > size)
- return;
- size -= newdata - data;
- data = newdata;
- n = size / PAGE_SIZE;
- size = n * PAGE_SIZE;
-
- mfns = malloc(n * sizeof(*mfns));
- for (i = 0; i < n; i++) {
-#ifdef LIBC_DEBUG
- int j;
- for (j=0; j<PAGE_SIZE; j++)
- if (((char*)data + i * PAGE_SIZE)[j]) {
- printk("%lx is not zero!\n", data + i * PAGE_SIZE + j);
- exit(1);
- }
-#endif
- mfns[i] = virtual_to_mfn(data + i * PAGE_SIZE);
- }
-
- printk("sparsing %ldMB at %lx\n", size >> 20, data);
-
- munmap((void *) data, size);
- free_physical_pages(mfns, n);
- do_map_zero(data, n);
-}
-
-int nice(int inc)
-{
- printk("nice() stub called with inc=%d\n", inc);
- return 0;
-}
-
-
-/* Not supported by FS yet. */
-unsupported_function_crash(link);
-unsupported_function(int, readlink, -1);
-unsupported_function_crash(umask);
-
-/* We could support that. */
-unsupported_function_log(int, chdir, -1);
-
-/* No dynamic library support. */
-unsupported_function_log(void *, dlopen, NULL);
-unsupported_function_log(void *, dlsym, NULL);
-unsupported_function_log(char *, dlerror, NULL);
-unsupported_function_log(int, dlclose, -1);
-
-/* We don't raise signals anyway. */
-unsupported_function(int, sigemptyset, -1);
-unsupported_function(int, sigfillset, -1);
-unsupported_function(int, sigaddset, -1);
-unsupported_function(int, sigdelset, -1);
-unsupported_function(int, sigismember, -1);
-unsupported_function(int, sigprocmask, -1);
-unsupported_function(int, sigaction, -1);
-unsupported_function(int, __sigsetjmp, 0);
-unsupported_function(int, sigaltstack, -1);
-unsupported_function_crash(kill);
-
-/* Unsupported */
-unsupported_function_crash(pipe);
-unsupported_function_crash(fork);
-unsupported_function_crash(execv);
-unsupported_function_crash(execve);
-unsupported_function_crash(waitpid);
-unsupported_function_crash(wait);
-unsupported_function_crash(lockf);
-unsupported_function_crash(sysconf);
-unsupported_function(int, tcsetattr, -1);
-unsupported_function(int, tcgetattr, 0);
-unsupported_function(int, grantpt, -1);
-unsupported_function(int, unlockpt, -1);
-unsupported_function(char *, ptsname, NULL);
-
-/* net/if.h */
-unsupported_function_log(unsigned int, if_nametoindex, -1);
-unsupported_function_log(char *, if_indextoname, (char *) NULL);
-unsupported_function_log(struct if_nameindex *, if_nameindex, (struct if_nameindex *) NULL);
-unsupported_function_crash(if_freenameindex);
-
-/* Linuxish abi for the Caml runtime, don't support
- Log, and return an error code if possible. If it is not possible
- to inform the application of an error, then crash instead!
-*/
-unsupported_function_log(struct dirent *, readdir64, NULL);
-unsupported_function_log(int, getrusage, -1);
-unsupported_function_log(int, getrlimit, -1);
-unsupported_function_log(int, getrlimit64, -1);
-unsupported_function_log(int, __xstat64, -1);
-unsupported_function_log(long, __strtol_internal, LONG_MIN);
-unsupported_function_log(double, __strtod_internal, HUGE_VAL);
-unsupported_function_log(int, utime, -1);
-unsupported_function_log(int, truncate64, -1);
-unsupported_function_log(int, tcflow, -1);
-unsupported_function_log(int, tcflush, -1);
-unsupported_function_log(int, tcdrain, -1);
-unsupported_function_log(int, tcsendbreak, -1);
-unsupported_function_log(int, cfsetospeed, -1);
-unsupported_function_log(int, cfsetispeed, -1);
-unsupported_function_crash(cfgetospeed);
-unsupported_function_crash(cfgetispeed);
-unsupported_function_log(int, symlink, -1);
-unsupported_function_log(const char*, inet_ntop, NULL);
-unsupported_function_crash(__fxstat64);
-unsupported_function_crash(__lxstat64);
-unsupported_function_log(int, socketpair, -1);
-unsupported_function_crash(sigsuspend);
-unsupported_function_log(int, sigpending, -1);
-unsupported_function_log(int, shutdown, -1);
-unsupported_function_log(int, setuid, -1);
-unsupported_function_log(int, setgid, -1);
-unsupported_function_crash(rewinddir);
-unsupported_function_log(int, getpriority, -1);
-unsupported_function_log(int, setpriority, -1);
-unsupported_function_log(int, mkfifo, -1);
-unsupported_function_log(int, getitimer, -1);
-unsupported_function_log(int, setitimer, -1);
-unsupported_function_log(void *, getservbyport, NULL);
-unsupported_function_log(void *, getservbyname, NULL);
-unsupported_function_log(void *, getpwuid, NULL);
-unsupported_function_log(void *, getpwnam, NULL);
-unsupported_function_log(void *, getprotobynumber, NULL);
-unsupported_function_log(void *, getprotobyname, NULL);
-unsupported_function_log(int, getpeername, -1);
-unsupported_function_log(int, getnameinfo, -1);
-unsupported_function_log(char *, getlogin, NULL);
-unsupported_function_crash(__h_errno_location);
-unsupported_function_log(int, gethostbyname_r, -1);
-unsupported_function_log(int, gethostbyaddr_r, -1);
-unsupported_function_log(int, getgroups, -1);
-unsupported_function_log(void *, getgrgid, NULL);
-unsupported_function_log(void *, getgrnam, NULL);
-unsupported_function_log(int, getaddrinfo, -1);
-unsupported_function_log(int, freeaddrinfo, -1);
-unsupported_function_log(int, ftruncate64, -1);
-unsupported_function_log(int, fchown, -1);
-unsupported_function_log(int, fchmod, -1);
-unsupported_function_crash(execvp);
-unsupported_function_log(int, dup, -1)
-unsupported_function_log(int, chroot, -1)
-unsupported_function_log(int, chown, -1);
-unsupported_function_log(int, chmod, -1);
-unsupported_function_crash(alarm);
-unsupported_function_log(int, inet_pton, -1);
-unsupported_function_log(int, access, -1);
-#endif
+++ /dev/null
-/*
- ****************************************************************************
- * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
- ****************************************************************************
- *
- * File: xmaloc.c
- * Author: Grzegorz Milos (gm281@cam.ac.uk)
- * Samuel Thibault (samuel.thibault@eu.citrix.com)
- * Changes:
- *
- * Date: Aug 2005
- * Jan 2008
- *
- * Environment: Xen Minimal OS
- * Description: simple memory allocator
- *
- ****************************************************************************
- * Simple allocator for Mini-os. If larger than a page, simply use the
- * page-order allocator.
- *
- * Copy of the allocator for Xen by Rusty Russell:
- * Copyright (C) 2005 Rusty Russell IBM Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <mini-os/os.h>
-#include <mini-os/mm.h>
-#include <mini-os/types.h>
-#include <mini-os/lib.h>
-#include <mini-os/list.h>
-#include <mini-os/xmalloc.h>
-
-#ifndef HAVE_LIBC
-/* static spinlock_t freelist_lock = SPIN_LOCK_UNLOCKED; */
-
-struct xmalloc_hdr
-{
- /* Total including this hdr, unused padding and second hdr. */
- size_t size;
- MINIOS_TAILQ_ENTRY(struct xmalloc_hdr) freelist;
-} __cacheline_aligned;
-
-static MINIOS_TAILQ_HEAD(,struct xmalloc_hdr) freelist =
- MINIOS_TAILQ_HEAD_INITIALIZER(freelist);
-
-/* Unused padding data between the two hdrs. */
-
-struct xmalloc_pad
-{
- /* Size including both hdrs. */
- size_t hdr_size;
-};
-
-/* Return size, increased to alignment with align. */
-static inline size_t align_up(size_t size, size_t align)
-{
- return (size + align - 1) & ~(align - 1);
-}
-
-static void maybe_split(struct xmalloc_hdr *hdr, size_t size, size_t block)
-{
- struct xmalloc_hdr *extra;
- size_t leftover;
- size = align_up(size, __alignof__(struct xmalloc_hdr));
- size = align_up(size, __alignof__(struct xmalloc_pad));
- leftover = block - size;
-
- /* If enough is left to make a block, put it on free list. */
- if ( leftover >= (2 * (sizeof(struct xmalloc_hdr) + sizeof(struct xmalloc_pad))) )
- {
- extra = (struct xmalloc_hdr *)((unsigned long)hdr + size);
- extra->size = leftover;
- /* spin_lock_irqsave(&freelist_lock, flags); */
- MINIOS_TAILQ_INSERT_HEAD(&freelist, extra, freelist);
- /* spin_unlock_irqrestore(&freelist_lock, flags); */
- }
- else
- {
- size = block;
- }
-
- hdr->size = size;
-}
-
-static struct xmalloc_hdr *xmalloc_new_page(size_t size)
-{
- struct xmalloc_hdr *hdr;
- /* unsigned long flags; */
-
- hdr = (struct xmalloc_hdr *)alloc_page();
- if ( hdr == NULL )
- return NULL;
-
- maybe_split(hdr, size, PAGE_SIZE);
-
- return hdr;
-}
-
-/* Big object? Just use the page allocator. */
-static void *xmalloc_whole_pages(size_t size, size_t align)
-{
- struct xmalloc_hdr *hdr;
- struct xmalloc_pad *pad;
- unsigned int pageorder;
- void *ret;
- /* Room for headers */
- size_t hdr_size = sizeof(struct xmalloc_hdr) + sizeof(struct xmalloc_pad);
- /* Align for actual beginning of data */
- hdr_size = align_up(hdr_size, align);
-
- pageorder = get_order(hdr_size + size);
-
- hdr = (struct xmalloc_hdr *)alloc_pages(pageorder);
- if ( hdr == NULL )
- return NULL;
-
- hdr->size = (1UL << (pageorder + PAGE_SHIFT));
-
- ret = (char*)hdr + hdr_size;
- pad = (struct xmalloc_pad *) ret - 1;
- pad->hdr_size = hdr_size;
- return ret;
-}
-
-void *_xmalloc(size_t size, size_t align)
-{
- struct xmalloc_hdr *i, *tmp, *hdr = NULL;
- uintptr_t data_begin;
- size_t hdr_size;
- /* unsigned long flags; */
-
- hdr_size = sizeof(struct xmalloc_hdr) + sizeof(struct xmalloc_pad);
- /* Align on headers requirements. */
- align = align_up(align, __alignof__(struct xmalloc_hdr));
- align = align_up(align, __alignof__(struct xmalloc_pad));
-
- /* For big allocs, give them whole pages. */
- if ( size + align_up(hdr_size, align) >= PAGE_SIZE )
- return xmalloc_whole_pages(size, align);
-
- /* Search free list. */
- /* spin_lock_irqsave(&freelist_lock, flags); */
- MINIOS_TAILQ_FOREACH_SAFE(i, &freelist, freelist, tmp)
- {
- data_begin = align_up((uintptr_t)i + hdr_size, align);
-
- if ( data_begin + size > (uintptr_t)i + i->size )
- continue;
-
- MINIOS_TAILQ_REMOVE(&freelist, i, freelist);
- /* spin_unlock_irqrestore(&freelist_lock, flags); */
-
- uintptr_t size_before = (data_begin - hdr_size) - (uintptr_t)i;
-
- if (size_before >= 2 * hdr_size) {
- /* Worth splitting the beginning */
- struct xmalloc_hdr *new_i = (void*)(data_begin - hdr_size);
- new_i->size = i->size - size_before;
- i->size = size_before;
- /* spin_lock_irqsave(&freelist_lock, flags); */
- MINIOS_TAILQ_INSERT_HEAD(&freelist, i, freelist);
- /* spin_unlock_irqrestore(&freelist_lock, flags); */
- i = new_i;
- }
- maybe_split(i, (data_begin + size) - (uintptr_t)i, i->size);
- hdr = i;
- break;
- }
-
- if (!hdr) {
- /* spin_unlock_irqrestore(&freelist_lock, flags); */
-
- /* Alloc a new page and return from that. */
- hdr = xmalloc_new_page(align_up(hdr_size, align) + size);
- if ( hdr == NULL )
- return NULL;
- data_begin = (uintptr_t)hdr + align_up(hdr_size, align);
- }
-
- struct xmalloc_pad *pad = (struct xmalloc_pad *) data_begin - 1;
- pad->hdr_size = data_begin - (uintptr_t)hdr;
- BUG_ON(data_begin % align);
- return (void*)data_begin;
-}
-
-void xfree(const void *p)
-{
- /* unsigned long flags; */
- struct xmalloc_hdr *i, *tmp, *hdr;
- struct xmalloc_pad *pad;
-
- if ( p == NULL )
- return;
-
- pad = (struct xmalloc_pad *)p - 1;
- hdr = (struct xmalloc_hdr *)((char *)p - pad->hdr_size);
-
- /* Big allocs free directly. */
- if ( hdr->size >= PAGE_SIZE )
- {
- free_pages(hdr, get_order(hdr->size));
- return;
- }
-
- /* We know hdr will be on same page. */
- if(((long)p & PAGE_MASK) != ((long)hdr & PAGE_MASK))
- {
- printk("Header should be on the same page\n");
- *(int*)0=0;
- }
-
- /* Merge with other free block, or put in list. */
- /* spin_lock_irqsave(&freelist_lock, flags); */
- MINIOS_TAILQ_FOREACH_SAFE(i, &freelist, freelist, tmp)
- {
- unsigned long _i = (unsigned long)i;
- unsigned long _hdr = (unsigned long)hdr;
-
- /* Do not merge across page boundaries. */
- if ( ((_i ^ _hdr) & PAGE_MASK) != 0 )
- continue;
-
- /* We follow this block? Swallow it. */
- if ( (_i + i->size) == _hdr )
- {
- MINIOS_TAILQ_REMOVE(&freelist, i, freelist);
- i->size += hdr->size;
- hdr = i;
- }
-
- /* We precede this block? Swallow it. */
- if ( (_hdr + hdr->size) == _i )
- {
- MINIOS_TAILQ_REMOVE(&freelist, i, freelist);
- hdr->size += i->size;
- }
- }
-
- /* Did we merge an entire page? */
- if ( hdr->size == PAGE_SIZE )
- {
- if((((unsigned long)hdr) & (PAGE_SIZE-1)) != 0)
- {
- printk("Bug\n");
- *(int*)0=0;
- }
- free_page(hdr);
- }
- else
- {
- MINIOS_TAILQ_INSERT_HEAD(&freelist, hdr, freelist);
- }
-
- /* spin_unlock_irqrestore(&freelist_lock, flags); */
-}
-
-void *malloc(size_t size)
-{
- return _xmalloc(size, DEFAULT_ALIGN);
-}
-
-void *realloc(void *ptr, size_t size)
-{
- void *new;
- struct xmalloc_hdr *hdr;
- struct xmalloc_pad *pad;
- size_t old_data_size;
-
- if (ptr == NULL)
- return _xmalloc(size, DEFAULT_ALIGN);
-
- pad = (struct xmalloc_pad *)ptr - 1;
- hdr = (struct xmalloc_hdr *)((char*)ptr - pad->hdr_size);
-
- old_data_size = hdr->size - pad->hdr_size;
- if ( old_data_size >= size )
- {
- maybe_split(hdr, pad->hdr_size + size, hdr->size);
- return ptr;
- }
-
- new = _xmalloc(size, DEFAULT_ALIGN);
- if (new == NULL)
- return NULL;
-
- memcpy(new, ptr, old_data_size);
- xfree(ptr);
-
- return new;
-}
-
-void free(void *ptr)
-{
- xfree(ptr);
-}
-#endif
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/*
- * libxs-compatible layer
- *
- * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, 2007-2008
- *
- * Mere wrapper around xenbus_*
- */
-
-#ifdef HAVE_LIBC
-#include <os.h>
-#include <lib.h>
-#include <xenstore.h>
-#include <xenbus.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-static inline int _xs_fileno(struct xs_handle *h) {
- return (intptr_t) h;
-}
-
-struct xs_handle *xs_daemon_open()
-{
- int fd = alloc_fd(FTYPE_XENBUS);
- files[fd].xenbus.events = NULL;
- printk("xs_daemon_open -> %d, %p\n", fd, &files[fd].xenbus.events);
- return (void*)(intptr_t) fd;
-}
-
-void xs_daemon_close(struct xs_handle *h)
-{
- int fd = _xs_fileno(h);
- struct xenbus_event *event, *next;
- for (event = files[fd].xenbus.events; event; event = next)
- {
- next = event->next;
- free(event);
- }
- files[fd].type = FTYPE_NONE;
-}
-
-int xs_fileno(struct xs_handle *h)
-{
- return _xs_fileno(h);
-}
-
-void *xs_read(struct xs_handle *h, xs_transaction_t t,
- const char *path, unsigned int *len)
-{
- char *value;
- char *msg;
-
- msg = xenbus_read(t, path, &value);
- if (msg) {
- printk("xs_read(%s): %s\n", path, msg);
- free(msg);
- return NULL;
- }
-
- if (len)
- *len = strlen(value);
- return value;
-}
-
-bool xs_write(struct xs_handle *h, xs_transaction_t t,
- const char *path, const void *data, unsigned int len)
-{
- char value[len + 1];
- char *msg;
-
- memcpy(value, data, len);
- value[len] = 0;
-
- msg = xenbus_write(t, path, value);
- if (msg) {
- printk("xs_write(%s): %s\n", path, msg);
- free(msg);
- return false;
- }
- return true;
-}
-
-static bool xs_bool(char *reply)
-{
- if (!reply)
- return true;
- free(reply);
- return false;
-}
-
-bool xs_rm(struct xs_handle *h, xs_transaction_t t, const char *path)
-{
- return xs_bool(xenbus_rm(t, path));
-}
-
-static void *xs_talkv(struct xs_handle *h, xs_transaction_t t,
- enum xsd_sockmsg_type type,
- struct write_req *iovec,
- unsigned int num_vecs,
- unsigned int *len)
-{
- struct xsd_sockmsg *msg;
- void *ret;
-
- msg = xenbus_msg_reply(type, t, iovec, num_vecs);
- ret = malloc(msg->len);
- memcpy(ret, (char*) msg + sizeof(*msg), msg->len);
- if (len)
- *len = msg->len - 1;
- free(msg);
- return ret;
-}
-
-static void *xs_single(struct xs_handle *h, xs_transaction_t t,
- enum xsd_sockmsg_type type,
- const char *string,
- unsigned int *len)
-{
- struct write_req iovec;
-
- iovec.data = (void *)string;
- iovec.len = strlen(string) + 1;
-
- return xs_talkv(h, t, type, &iovec, 1, len);
-}
-
-char *xs_get_domain_path(struct xs_handle *h, unsigned int domid)
-{
- char domid_str[MAX_STRLEN(domid)];
-
- sprintf(domid_str, "%u", domid);
-
- return xs_single(h, XBT_NULL, XS_GET_DOMAIN_PATH, domid_str, NULL);
-}
-
-char **xs_directory(struct xs_handle *h, xs_transaction_t t,
- const char *path, unsigned int *num)
-{
- char *msg;
- char **entries, **res;
- char *entry;
- int i, n;
- int size;
-
- msg = xenbus_ls(t, path, &res);
- if (msg) {
- printk("xs_directory(%s): %s\n", path, msg);
- free(msg);
- return NULL;
- }
-
- size = 0;
- for (n = 0; res[n]; n++)
- size += strlen(res[n]) + 1;
-
- entries = malloc(n * sizeof(char *) + size);
- entry = (char *) (&entries[n]);
-
- for (i = 0; i < n; i++) {
- int l = strlen(res[i]) + 1;
- memcpy(entry, res[i], l);
- free(res[i]);
- entries[i] = entry;
- entry += l;
- }
-
- *num = n;
- free(res);
- return entries;
-}
-
-bool xs_watch(struct xs_handle *h, const char *path, const char *token)
-{
- int fd = _xs_fileno(h);
- printk("xs_watch(%s, %s)\n", path, token);
- return xs_bool(xenbus_watch_path_token(XBT_NULL, path, token, &files[fd].xenbus.events));
-}
-
-char **xs_read_watch(struct xs_handle *h, unsigned int *num)
-{
- int fd = _xs_fileno(h);
- struct xenbus_event *event;
- event = files[fd].xenbus.events;
- files[fd].xenbus.events = event->next;
- printk("xs_read_watch() -> %s %s\n", event->path, event->token);
- *num = 2;
- return (char **) &event->path;
-}
-
-bool xs_unwatch(struct xs_handle *h, const char *path, const char *token)
-{
- printk("xs_unwatch(%s, %s)\n", path, token);
- return xs_bool(xenbus_unwatch_path_token(XBT_NULL, path, token));
-}
-#endif
+++ /dev/null
-/*
- * locks for newlib
- *
- * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, July 20008
- */
-
-#ifdef HAVE_LIBC
-
-#include <sys/lock.h>
-#include <sched.h>
-#include <wait.h>
-#include <mini-os/lib.h>
-
-int ___lock_init(_LOCK_T *lock)
-{
- lock->busy = 0;
- init_waitqueue_head(&lock->wait);
- return 0;
-}
-
-int ___lock_acquire(_LOCK_T *lock)
-{
- unsigned long flags;
- while(1) {
- wait_event(lock->wait, !lock->busy);
- local_irq_save(flags);
- if (!lock->busy)
- break;
- local_irq_restore(flags);
- }
- lock->busy = 1;
- local_irq_restore(flags);
- return 0;
-}
-
-int ___lock_try_acquire(_LOCK_T *lock)
-{
- unsigned long flags;
- int ret = -1;
- local_irq_save(flags);
- if (!lock->busy) {
- lock->busy = 1;
- ret = 0;
- }
- local_irq_restore(flags);
- return ret;
-}
-
-int ___lock_release(_LOCK_T *lock)
-{
- unsigned long flags;
- local_irq_save(flags);
- lock->busy = 0;
- wake_up(&lock->wait);
- local_irq_restore(flags);
- return 0;
-}
-
-
-int ___lock_init_recursive(_LOCK_RECURSIVE_T *lock)
-{
- lock->owner = NULL;
- init_waitqueue_head(&lock->wait);
- return 0;
-}
-
-int ___lock_acquire_recursive(_LOCK_RECURSIVE_T *lock)
-{
- unsigned long flags;
- if (lock->owner != get_current()) {
- while (1) {
- wait_event(lock->wait, lock->owner == NULL);
- local_irq_save(flags);
- if (lock->owner == NULL)
- break;
- local_irq_restore(flags);
- }
- lock->owner = get_current();
- local_irq_restore(flags);
- }
- lock->count++;
- return 0;
-}
-
-int ___lock_try_acquire_recursive(_LOCK_RECURSIVE_T *lock)
-{
- unsigned long flags;
- int ret = -1;
- local_irq_save(flags);
- if (!lock->owner) {
- ret = 0;
- lock->owner = get_current();
- lock->count++;
- }
- local_irq_restore(flags);
- return ret;
-}
-
-int ___lock_release_recursive(_LOCK_RECURSIVE_T *lock)
-{
- unsigned long flags;
- BUG_ON(lock->owner != get_current());
- if (--lock->count)
- return 0;
- local_irq_save(flags);
- lock->owner = NULL;
- wake_up(&lock->wait);
- local_irq_restore(flags);
- return 0;
-}
-
-#endif
+++ /dev/null
-/*
- * lwip-arch.c
- *
- * Arch-specific semaphores and mailboxes for lwIP running on mini-os
- *
- * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
- */
-
-#include <os.h>
-#include <time.h>
-#include <console.h>
-#include <xmalloc.h>
-#include <lwip/sys.h>
-#include <stdarg.h>
-
-/* Is called to initialize the sys_arch layer */
-void sys_init(void)
-{
-}
-
-/* Creates and returns a new semaphore. The "count" argument specifies
- * the initial state of the semaphore. */
-sys_sem_t sys_sem_new(uint8_t count)
-{
- struct semaphore *sem = xmalloc(struct semaphore);
- sem->count = count;
- init_waitqueue_head(&sem->wait);
- return sem;
-}
-
-/* Deallocates a semaphore. */
-void sys_sem_free(sys_sem_t sem)
-{
- xfree(sem);
-}
-
-/* Signals a semaphore. */
-void sys_sem_signal(sys_sem_t sem)
-{
- up(sem);
-}
-
-/* Blocks the thread while waiting for the semaphore to be
- * signaled. If the "timeout" argument is non-zero, the thread should
- * only be blocked for the specified time (measured in
- * milliseconds).
- *
- * If the timeout argument is non-zero, the return value is the number of
- * milliseconds spent waiting for the semaphore to be signaled. If the
- * semaphore wasn't signaled within the specified time, the return value is
- * SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
- * (i.e., it was already signaled), the function may return zero. */
-uint32_t sys_arch_sem_wait(sys_sem_t sem, uint32_t timeout)
-{
- /* Slightly more complicated than the normal minios semaphore:
- * need to wake on timeout *or* signal */
- sys_prot_t prot;
- int64_t then = NOW();
- int64_t deadline;
-
- if (timeout == 0)
- deadline = 0;
- else
- deadline = then + MILLISECS(timeout);
-
- while(1) {
- wait_event_deadline(sem->wait, (sem->count > 0), deadline);
-
- prot = sys_arch_protect();
- /* Atomically check that we can proceed */
- if (sem->count > 0 || (deadline && NOW() >= deadline))
- break;
- sys_arch_unprotect(prot);
- }
-
- if (sem->count > 0) {
- sem->count--;
- sys_arch_unprotect(prot);
- return NSEC_TO_MSEC(NOW() - then);
- }
-
- sys_arch_unprotect(prot);
- return SYS_ARCH_TIMEOUT;
-}
-
-/* Creates an empty mailbox. */
-sys_mbox_t sys_mbox_new(int size)
-{
- struct mbox *mbox = xmalloc(struct mbox);
- if (!size)
- size = 32;
- else if (size == 1)
- size = 2;
- mbox->count = size;
- mbox->messages = xmalloc_array(void*, size);
- init_SEMAPHORE(&mbox->read_sem, 0);
- mbox->reader = 0;
- init_SEMAPHORE(&mbox->write_sem, size);
- mbox->writer = 0;
- return mbox;
-}
-
-/* Deallocates a mailbox. If there are messages still present in the
- * mailbox when the mailbox is deallocated, it is an indication of a
- * programming error in lwIP and the developer should be notified. */
-void sys_mbox_free(sys_mbox_t mbox)
-{
- ASSERT(mbox->reader == mbox->writer);
- xfree(mbox->messages);
- xfree(mbox);
-}
-
-/* Posts the "msg" to the mailbox, internal version that actually does the
- * post. */
-static void do_mbox_post(sys_mbox_t mbox, void *msg)
-{
- /* The caller got a semaphore token, so we are now allowed to increment
- * writer, but we still need to prevent concurrency between writers
- * (interrupt handler vs main) */
- sys_prot_t prot = sys_arch_protect();
- mbox->messages[mbox->writer] = msg;
- mbox->writer = (mbox->writer + 1) % mbox->count;
- ASSERT(mbox->reader != mbox->writer);
- sys_arch_unprotect(prot);
- up(&mbox->read_sem);
-}
-
-/* Posts the "msg" to the mailbox. */
-void sys_mbox_post(sys_mbox_t mbox, void *msg)
-{
- if (mbox == SYS_MBOX_NULL)
- return;
- down(&mbox->write_sem);
- do_mbox_post(mbox, msg);
-}
-
-/* Try to post the "msg" to the mailbox. */
-err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg)
-{
- if (mbox == SYS_MBOX_NULL)
- return ERR_BUF;
- if (!trydown(&mbox->write_sem))
- return ERR_MEM;
- do_mbox_post(mbox, msg);
- return ERR_OK;
-}
-
-/*
- * Fetch a message from a mailbox. Internal version that actually does the
- * fetch.
- */
-static void do_mbox_fetch(sys_mbox_t mbox, void **msg)
-{
- sys_prot_t prot;
- /* The caller got a semaphore token, so we are now allowed to increment
- * reader, but we may still need to prevent concurrency between readers.
- * FIXME: can there be concurrent readers? */
- prot = sys_arch_protect();
- ASSERT(mbox->reader != mbox->writer);
- if (msg != NULL)
- *msg = mbox->messages[mbox->reader];
- mbox->reader = (mbox->reader + 1) % mbox->count;
- sys_arch_unprotect(prot);
- up(&mbox->write_sem);
-}
-
-/* Blocks the thread until a message arrives in the mailbox, but does
- * not block the thread longer than "timeout" milliseconds (similar to
- * the sys_arch_sem_wait() function). The "msg" argument is a result
- * parameter that is set by the function (i.e., by doing "*msg =
- * ptr"). The "msg" parameter maybe NULL to indicate that the message
- * should be dropped.
- *
- * The return values are the same as for the sys_arch_sem_wait() function:
- * Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
- * timeout. */
-uint32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, uint32_t timeout)
-{
- uint32_t rv;
- if (mbox == SYS_MBOX_NULL)
- return SYS_ARCH_TIMEOUT;
-
- rv = sys_arch_sem_wait(&mbox->read_sem, timeout);
- if ( rv == SYS_ARCH_TIMEOUT )
- return rv;
-
- do_mbox_fetch(mbox, msg);
- return 0;
-}
-
-/* This is similar to sys_arch_mbox_fetch, however if a message is not
- * present in the mailbox, it immediately returns with the code
- * SYS_MBOX_EMPTY. On success 0 is returned.
- *
- * To allow for efficient implementations, this can be defined as a
- * function-like macro in sys_arch.h instead of a normal function. For
- * example, a naive implementation could be:
- * #define sys_arch_mbox_tryfetch(mbox,msg) \
- * sys_arch_mbox_fetch(mbox,msg,1)
- * although this would introduce unnecessary delays. */
-
-uint32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg) {
- if (mbox == SYS_MBOX_NULL)
- return SYS_ARCH_TIMEOUT;
-
- if (!trydown(&mbox->read_sem))
- return SYS_MBOX_EMPTY;
-
- do_mbox_fetch(mbox, msg);
- return 0;
-}
-
-
-/* Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
- * each thread has a list of timeouts which is repressented as a linked
- * list of sys_timeout structures. The sys_timeouts structure holds a
- * pointer to a linked list of timeouts. This function is called by
- * the lwIP timeout scheduler and must not return a NULL value.
- *
- * In a single threadd sys_arch implementation, this function will
- * simply return a pointer to a global sys_timeouts variable stored in
- * the sys_arch module. */
-struct sys_timeouts *sys_arch_timeouts(void)
-{
- static struct sys_timeouts timeout;
- return &timeout;
-}
-
-
-/* Starts a new thread with priority "prio" that will begin its execution in the
- * function "thread()". The "arg" argument will be passed as an argument to the
- * thread() function. The id of the new thread is returned. Both the id and
- * the priority are system dependent. */
-static struct thread *lwip_thread;
-sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio)
-{
- struct thread *t;
- if (stacksize > STACK_SIZE) {
- printk("Can't start lwIP thread: stack size %d is too large for our %d\n", stacksize, STACK_SIZE);
- do_exit();
- }
- lwip_thread = t = create_thread(name, thread, arg);
- return t;
-}
-
-/* This optional function does a "fast" critical region protection and returns
- * the previous protection level. This function is only called during very short
- * critical regions. An embedded system which supports ISR-based drivers might
- * want to implement this function by disabling interrupts. Task-based systems
- * might want to implement this by using a mutex or disabling tasking. This
- * function should support recursive calls from the same task or interrupt. In
- * other words, sys_arch_protect() could be called while already protected. In
- * that case the return value indicates that it is already protected.
- *
- * sys_arch_protect() is only required if your port is supporting an operating
- * system. */
-sys_prot_t sys_arch_protect(void)
-{
- unsigned long flags;
- local_irq_save(flags);
- return flags;
-}
-
-/* This optional function does a "fast" set of critical region protection to the
- * value specified by pval. See the documentation for sys_arch_protect() for
- * more information. This function is only required if your port is supporting
- * an operating system. */
-void sys_arch_unprotect(sys_prot_t pval)
-{
- local_irq_restore(pval);
-}
-
-/* non-fatal, print a message. */
-void lwip_printk(char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- printk("lwIP: ");
- print(0, fmt, args);
- va_end(args);
-}
-
-/* fatal, print message and abandon execution. */
-void lwip_die(char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- printk("lwIP assertion failed: ");
- print(0, fmt, args);
- va_end(args);
- printk("\n");
- BUG();
-}
+++ /dev/null
-/*
- * lwip-net.c
- *
- * interface between lwIP's ethernet and Mini-os's netfront.
- * For now, support only one network interface, as mini-os does.
- *
- * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
- * based on lwIP's ethernetif.c skeleton file, copyrights as below.
- */
-
-
-/*
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include <os.h>
-
-#include "lwip/opt.h"
-#include "lwip/def.h"
-#include "lwip/mem.h"
-#include "lwip/pbuf.h"
-#include "lwip/sys.h"
-
-#include <lwip/stats.h>
-#include <lwip/sys.h>
-#include <lwip/mem.h>
-#include <lwip/memp.h>
-#include <lwip/pbuf.h>
-#include <netif/etharp.h>
-#include <lwip/tcpip.h>
-#include <lwip/tcp.h>
-#include <lwip/netif.h>
-#include <lwip/dhcp.h>
-
-#include "netif/etharp.h"
-
-#include <netfront.h>
-
-/* Define those to better describe your network interface. */
-#define IFNAME0 'e'
-#define IFNAME1 'n'
-
-#define IF_IPADDR 0x00000000
-#define IF_NETMASK 0x00000000
-
-/* Only have one network interface at a time. */
-static struct netif *the_interface = NULL;
-
-static unsigned char rawmac[6];
-static struct netfront_dev *dev;
-
-/* Forward declarations. */
-static err_t netfront_output(struct netif *netif, struct pbuf *p,
- struct ip_addr *ipaddr);
-
-/*
- * low_level_output():
- *
- * Should do the actual transmission of the packet. The packet is
- * contained in the pbuf that is passed to the function. This pbuf
- * might be chained.
- *
- */
-
-static err_t
-low_level_output(struct netif *netif, struct pbuf *p)
-{
- if (!dev)
- return ERR_OK;
-
-#ifdef ETH_PAD_SIZE
- pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
-#endif
-
- /* Send the data from the pbuf to the interface, one pbuf at a
- time. The size of the data in each pbuf is kept in the ->len
- variable. */
- if (!p->next) {
- /* Only one fragment, can send it directly */
- netfront_xmit(dev, p->payload, p->len);
- } else {
- unsigned char data[p->tot_len], *cur;
- struct pbuf *q;
-
- for(q = p, cur = data; q != NULL; cur += q->len, q = q->next)
- memcpy(cur, q->payload, q->len);
- netfront_xmit(dev, data, p->tot_len);
- }
-
-#if ETH_PAD_SIZE
- pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
-#endif
-
- LINK_STATS_INC(link.xmit);
-
- return ERR_OK;
-}
-
-
-
-/*
- * netfront_output():
- *
- * This function is called by the TCP/IP stack when an IP packet
- * should be sent. It calls the function called low_level_output() to
- * do the actual transmission of the packet.
- *
- */
-
-static err_t
-netfront_output(struct netif *netif, struct pbuf *p,
- struct ip_addr *ipaddr)
-{
-
- /* resolve hardware address, then send (or queue) packet */
- return etharp_output(netif, p, ipaddr);
-
-}
-
-/*
- * netfront_input():
- *
- * This function should be called when a packet is ready to be read
- * from the interface.
- *
- */
-
-static void
-netfront_input(struct netif *netif, unsigned char* data, int len)
-{
- struct eth_hdr *ethhdr;
- struct pbuf *p, *q;
-
-#if ETH_PAD_SIZE
- len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
-#endif
-
- /* move received packet into a new pbuf */
- p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
- if (p == NULL) {
- LINK_STATS_INC(link.memerr);
- LINK_STATS_INC(link.drop);
- return;
- }
-
-#if ETH_PAD_SIZE
- pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
-#endif
-
- /* We iterate over the pbuf chain until we have read the entire
- * packet into the pbuf. */
- for(q = p; q != NULL && len > 0; q = q->next) {
- /* Read enough bytes to fill this pbuf in the chain. The
- * available data in the pbuf is given by the q->len
- * variable. */
- memcpy(q->payload, data, len < q->len ? len : q->len);
- data += q->len;
- len -= q->len;
- }
-
-#if ETH_PAD_SIZE
- pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
-#endif
-
- LINK_STATS_INC(link.recv);
-
- /* points to packet payload, which starts with an Ethernet header */
- ethhdr = p->payload;
-
- switch (htons(ethhdr->type)) {
- /* IP packet? */
- case ETHTYPE_IP:
-#if 0
-/* CSi disabled ARP table update on ingress IP packets.
- This seems to work but needs thorough testing. */
- /* update ARP table */
- etharp_ip_input(netif, p);
-#endif
- /* skip Ethernet header */
- pbuf_header(p, -(int16_t)sizeof(struct eth_hdr));
- /* pass to network layer */
- if (tcpip_input(p, netif) == ERR_MEM)
- /* Could not store it, drop */
- pbuf_free(p);
- break;
-
- case ETHTYPE_ARP:
- /* pass p to ARP module */
- etharp_arp_input(netif, (struct eth_addr *) netif->hwaddr, p);
- break;
-
- default:
- pbuf_free(p);
- p = NULL;
- break;
- }
-}
-
-
-/*
- * netif_rx(): overrides the default netif_rx behaviour in the netfront driver.
- *
- * Pull received packets into a pbuf queue for the low_level_input()
- * function to pass up to lwIP.
- */
-
-void netif_rx(unsigned char* data, int len)
-{
- if (the_interface != NULL) {
- netfront_input(the_interface, data, len);
- wake_up(&netfront_queue);
- }
- /* By returning, we ack the packet and relinquish the RX ring slot */
-}
-
-/*
- * Set the IP, mask and gateway of the IF
- */
-void networking_set_addr(struct ip_addr *ipaddr, struct ip_addr *netmask, struct ip_addr *gw)
-{
- netif_set_ipaddr(the_interface, ipaddr);
- netif_set_netmask(the_interface, netmask);
- netif_set_gw(the_interface, gw);
-}
-
-
-static void
-arp_timer(void *arg)
-{
- etharp_tmr();
- sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
-}
-
-/*
- * netif_netfront_init():
- *
- * Should be called at the beginning of the program to set up the
- * network interface. It calls the function low_level_init() to do the
- * actual setup of the hardware.
- *
- */
-
-err_t
-netif_netfront_init(struct netif *netif)
-{
- unsigned char *mac = netif->state;
-
-#if LWIP_SNMP
- /* ifType ethernetCsmacd(6) @see RFC1213 */
- netif->link_type = 6;
- /* your link speed here */
- netif->link_speed = ;
- netif->ts = 0;
- netif->ifinoctets = 0;
- netif->ifinucastpkts = 0;
- netif->ifinnucastpkts = 0;
- netif->ifindiscards = 0;
- netif->ifoutoctets = 0;
- netif->ifoutucastpkts = 0;
- netif->ifoutnucastpkts = 0;
- netif->ifoutdiscards = 0;
-#endif
-
- netif->name[0] = IFNAME0;
- netif->name[1] = IFNAME1;
- netif->output = netfront_output;
- netif->linkoutput = low_level_output;
-
- the_interface = netif;
-
- /* set MAC hardware address */
- netif->hwaddr_len = 6;
- netif->hwaddr[0] = mac[0];
- netif->hwaddr[1] = mac[1];
- netif->hwaddr[2] = mac[2];
- netif->hwaddr[3] = mac[3];
- netif->hwaddr[4] = mac[4];
- netif->hwaddr[5] = mac[5];
-
- /* No interesting per-interface state */
- netif->state = NULL;
-
- /* maximum transfer unit */
- netif->mtu = 1500;
-
- /* broadcast capability */
- netif->flags = NETIF_FLAG_BROADCAST;
-
- etharp_init();
-
- sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
-
- return ERR_OK;
-}
-
-/*
- * Thread run by netfront: bring up the IP address and fire lwIP timers.
- */
-static __DECLARE_SEMAPHORE_GENERIC(tcpip_is_up, 0);
-static void tcpip_bringup_finished(void *p)
-{
- tprintk("TCP/IP bringup ends.\n");
- up(&tcpip_is_up);
-}
-
-/*
- * Utility function to bring the whole lot up. Call this from app_main()
- * or similar -- it starts netfront and have lwIP start its thread,
- * which calls back to tcpip_bringup_finished(), which
- * lets us know it's OK to continue.
- */
-void start_networking(void)
-{
- struct netif *netif;
- struct ip_addr ipaddr = { htonl(IF_IPADDR) };
- struct ip_addr netmask = { htonl(IF_NETMASK) };
- struct ip_addr gw = { 0 };
- char *ip = NULL;
-
- tprintk("Waiting for network.\n");
-
- dev = init_netfront(NULL, NULL, rawmac, &ip);
-
- if (ip) {
- ipaddr.addr = inet_addr(ip);
- if (IN_CLASSA(ntohl(ipaddr.addr)))
- netmask.addr = htonl(IN_CLASSA_NET);
- else if (IN_CLASSB(ntohl(ipaddr.addr)))
- netmask.addr = htonl(IN_CLASSB_NET);
- else if (IN_CLASSC(ntohl(ipaddr.addr)))
- netmask.addr = htonl(IN_CLASSC_NET);
- else
- tprintk("Strange IP %s, leaving netmask to 0.\n", ip);
- }
- tprintk("IP %x netmask %x gateway %x.\n",
- ntohl(ipaddr.addr), ntohl(netmask.addr), ntohl(gw.addr));
-
- tprintk("TCP/IP bringup begins.\n");
-
- netif = xmalloc(struct netif);
- tcpip_init(tcpip_bringup_finished, netif);
-
- netif_add(netif, &ipaddr, &netmask, &gw, rawmac,
- netif_netfront_init, ip_input);
- netif_set_default(netif);
- netif_set_up(netif);
-
- down(&tcpip_is_up);
-
- tprintk("Network is ready.\n");
-}
-
-/* Shut down the network */
-void stop_networking(void)
-{
- if (dev)
- shutdown_netfront(dev);
-}
+++ /dev/null
-/*
- * POSIX-compatible main layer
- *
- * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, October 2007
- */
-
-#ifdef HAVE_LIBC
-#include <os.h>
-#include <sched.h>
-#include <console.h>
-#include <netfront.h>
-#include <pcifront.h>
-#include <time.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <xenbus.h>
-#include <events.h>
-#include <mini-os/lib.h>
-
-extern int main(int argc, char *argv[], char *envp[]);
-extern void __libc_init_array(void);
-extern void __libc_fini_array(void);
-extern unsigned long __CTOR_LIST__[];
-extern unsigned long __DTOR_LIST__[];
-
-#if 0
-#include <stdio.h>
-int main(int argc, char *argv[], char *envp[])
-{
- printf("Hello, World!\n");
- return 1;
-}
-#endif
-
-void _init(void)
-{
-}
-
-void _fini(void)
-{
-}
-
-extern char __app_bss_start, __app_bss_end;
-static void call_main(void *p)
-{
- char *c, quote;
-#ifdef CONFIG_QEMU_XS_ARGS
- char *domargs, *msg;
-#endif
- int argc;
- char **argv;
- char *envp[] = { NULL };
-#ifdef CONFIG_QEMU_XS_ARGS
- char *vm;
- char path[128];
- int domid;
-#endif
- int i;
-
- /* Let other parts initialize (including console output) before maybe
- * crashing. */
- //sleep(1);
-
-#ifdef CONFIG_SPARSE_BSS
- sparse((unsigned long) &__app_bss_start, &__app_bss_end - &__app_bss_start);
-#endif
-#if defined(HAVE_LWIP) && defined(CONFIG_START_NETWORK) && defined(CONFIG_NETFRONT)
- start_networking();
-#endif
-#ifdef CONFIG_PCIFRONT
- create_thread("pcifront", pcifront_watches, NULL);
-#endif
-
-#ifdef CONFIG_QEMU_XS_ARGS
- /* Fetch argc, argv from XenStore */
- domid = xenbus_read_integer("target");
- if (domid == -1) {
- printk("Couldn't read target\n");
- do_exit();
- }
-
- snprintf(path, sizeof(path), "/local/domain/%d/vm", domid);
- msg = xenbus_read(XBT_NIL, path, &vm);
- if (msg) {
- printk("Couldn't read vm path\n");
- do_exit();
- }
- printk("dom vm is at %s\n", vm);
-
- snprintf(path, sizeof(path), "%s/image/dmargs", vm);
- free(vm);
- msg = xenbus_read(XBT_NIL, path, &domargs);
-
- if (msg) {
- printk("Couldn't get stubdom args: %s\n", msg);
- domargs = strdup("");
- }
-#endif
-
- argc = 1;
-
-#define PARSE_ARGS(ARGS,START,QUOTE,END) \
- c = ARGS; \
- quote = 0; \
- while (*c) { \
- if (*c != ' ') { \
- START; \
- while (*c) { \
- if (quote) { \
- if (*c == quote) { \
- quote = 0; \
- QUOTE; \
- continue; \
- } \
- } else if (*c == ' ') \
- break; \
- if (*c == '"' || *c == '\'') { \
- quote = *c; \
- QUOTE; \
- continue; \
- } \
- c++; \
- } \
- } else { \
- END; \
- while (*c == ' ') \
- c++; \
- } \
- } \
- if (quote) {\
- printk("Warning: unterminated quotation %c\n", quote); \
- quote = 0; \
- }
-#define PARSE_ARGS_COUNT(ARGS) PARSE_ARGS(ARGS, argc++, c++, )
-#define PARSE_ARGS_STORE(ARGS) PARSE_ARGS(ARGS, argv[argc++] = c, memmove(c, c + 1, strlen(c + 1) + 1), *c++ = 0)
-
- PARSE_ARGS_COUNT((char*)start_info.cmd_line);
-#ifdef CONFIG_QEMU_XS_ARGS
- PARSE_ARGS_COUNT(domargs);
-#endif
-
- argv = alloca((argc + 1) * sizeof(char *));
- argv[0] = "main";
- argc = 1;
-
- PARSE_ARGS_STORE((char*)start_info.cmd_line)
-#ifdef CONFIG_QEMU_XS_ARGS
- PARSE_ARGS_STORE(domargs)
-#endif
-
- argv[argc] = NULL;
-
- for (i = 0; i < argc; i++)
- printf("\"%s\" ", argv[i]);
- printf("\n");
-
- __libc_init_array();
- environ = envp;
- for (i = 0; __CTOR_LIST__[i] != 0; i++)
- ((void((*)(void)))__CTOR_LIST__[i]) ();
- tzset();
-
- exit(main(argc, argv, envp));
-}
-
-void _exit(int ret)
-{
- int i;
-
- for (i = 0; __DTOR_LIST__[i] != 0; i++)
- ((void((*)(void)))__DTOR_LIST__[i]) ();
- close_all_files();
- __libc_fini_array();
- printk("main returned %d\n", ret);
-#if defined(HAVE_LWIP) && defined(CONFIG_NETFRONT)
- stop_networking();
-#endif
- stop_kernel();
- if (!ret) {
- /* No problem, just shutdown. */
- struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_poweroff };
- HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
- }
- do_exit();
-}
-
-int app_main(start_info_t *si)
-{
- printk("main.c: dummy main: start_info=%p\n", si);
- main_thread = create_thread("main", call_main, si);
- return 0;
-}
-#endif
+++ /dev/null
-#
-# The file contains the common make rules for building mini-os.
-#
-
-debug = y
-
-# Define some default flags.
-# NB. '-Wcast-qual' is nasty, so I omitted it.
-DEF_CFLAGS += -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format -Wno-redundant-decls
-DEF_CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
-DEF_CFLAGS += $(call cc-option,$(CC),-fgnu89-inline)
-DEF_CFLAGS += -Wstrict-prototypes -Wnested-externs -Wpointer-arith -Winline
-DEF_CPPFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION)
-
-DEF_ASFLAGS += -D__ASSEMBLY__
-DEF_LDFLAGS +=
-
-ifeq ($(debug),y)
-DEF_CFLAGS += -g
-#DEF_CFLAGS += -DMM_DEBUG
-#DEF_CFLAGS += -DFS_DEBUG
-#DEF_CFLAGS += -DLIBC_DEBUG
-#DEF_CFLAGS += -DGNT_DEBUG
-#DEF_CFLAGS += -DGNTMAP_DEBUG
-else
-DEF_CFLAGS += -O3
-endif
-
-# Make the headers define our internal stuff
-DEF_CFLAGS += -D__INSIDE_MINIOS__
-
-# Build the CFLAGS and ASFLAGS for compiling and assembling.
-# DEF_... flags are the common mini-os flags,
-# ARCH_... flags may be defined in arch/$(TARGET_ARCH_FAM/rules.mk
-CFLAGS := $(DEF_CFLAGS) $(ARCH_CFLAGS)
-CPPFLAGS := $(DEF_CPPFLAGS) $(ARCH_CPPFLAGS)
-ASFLAGS := $(DEF_ASFLAGS) $(ARCH_ASFLAGS)
-LDFLAGS := $(DEF_LDFLAGS) $(ARCH_LDFLAGS)
-
-# Special build dependencies.
-# Rebuild all after touching this/these file(s)
-EXTRA_DEPS += $(MINI-OS_ROOT)/minios.mk
-EXTRA_DEPS += $(MINI-OS_ROOT)/$(TARGET_ARCH_DIR)/arch.mk
-
-# Find all header files for checking dependencies.
-HDRS := $(wildcard $(MINI-OS_ROOT)/include/*.h)
-HDRS += $(wildcard $(MINI-OS_ROOT)/include/xen/*.h)
-HDRS += $(wildcard $(ARCH_INC)/*.h)
-# For special wanted header directories.
-extra_heads := $(foreach dir,$(EXTRA_INC),$(wildcard $(dir)/*.h))
-HDRS += $(extra_heads)
-
-# Add the special header directories to the include paths.
-override CPPFLAGS := $(CPPFLAGS) $(extra_incl)
-
-# The name of the architecture specific library.
-# This is on x86_32: libx86_32.a
-# $(ARCH_LIB) has to built in the architecture specific directory.
-ARCH_LIB_NAME = $(MINIOS_TARGET_ARCH)
-ARCH_LIB := lib$(ARCH_LIB_NAME).a
-
-# This object contains the entrypoint for startup from Xen.
-# $(HEAD_ARCH_OBJ) has to be built in the architecture specific directory.
-HEAD_ARCH_OBJ := $(MINIOS_TARGET_ARCH).o
-HEAD_OBJ := $(OBJ_DIR)/$(TARGET_ARCH_DIR)/$(HEAD_ARCH_OBJ)
-
-
-$(OBJ_DIR)/%.o: %.c $(HDRS) Makefile $(EXTRA_DEPS)
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
-
-$(OBJ_DIR)/%.o: %.S $(HDRS) Makefile $(EXTRA_DEPS)
- $(CC) $(ASFLAGS) $(CPPFLAGS) -c $< -o $@
-
-
-
-
+++ /dev/null
-/*
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
- ****************************************************************************
- *
- * File: mm.c
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes: Grzegorz Milos
- *
- * Date: Aug 2003, chages Aug 2005
- *
- * Environment: Xen Minimal OS
- * Description: memory management related functions
- * contains buddy page allocator from Xen.
- *
- ****************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <mini-os/os.h>
-#include <mini-os/hypervisor.h>
-#include <xen/memory.h>
-#include <mini-os/mm.h>
-#include <mini-os/types.h>
-#include <mini-os/lib.h>
-#include <mini-os/xmalloc.h>
-
-#ifdef MM_DEBUG
-#define DEBUG(_f, _a...) \
- printk("MINI_OS(file=mm.c, line=%d) " _f "\n", __LINE__, ## _a)
-#else
-#define DEBUG(_f, _a...) ((void)0)
-#endif
-
-/*********************
- * ALLOCATION BITMAP
- * One bit per page of memory. Bit set => page is allocated.
- */
-
-static unsigned long *alloc_bitmap;
-#define PAGES_PER_MAPWORD (sizeof(unsigned long) * 8)
-
-#define allocated_in_map(_pn) \
-(alloc_bitmap[(_pn)/PAGES_PER_MAPWORD] & (1UL<<((_pn)&(PAGES_PER_MAPWORD-1))))
-
-/*
- * Hint regarding bitwise arithmetic in map_{alloc,free}:
- * -(1<<n) sets all bits >= n.
- * (1<<n)-1 sets all bits < n.
- * Variable names in map_{alloc,free}:
- * *_idx == Index into `alloc_bitmap' array.
- * *_off == Bit offset within an element of the `alloc_bitmap' array.
- */
-
-static void map_alloc(unsigned long first_page, unsigned long nr_pages)
-{
- unsigned long start_off, end_off, curr_idx, end_idx;
-
- curr_idx = first_page / PAGES_PER_MAPWORD;
- start_off = first_page & (PAGES_PER_MAPWORD-1);
- end_idx = (first_page + nr_pages) / PAGES_PER_MAPWORD;
- end_off = (first_page + nr_pages) & (PAGES_PER_MAPWORD-1);
-
- if ( curr_idx == end_idx )
- {
- alloc_bitmap[curr_idx] |= ((1UL<<end_off)-1) & -(1UL<<start_off);
- }
- else
- {
- alloc_bitmap[curr_idx] |= -(1UL<<start_off);
- while ( ++curr_idx < end_idx ) alloc_bitmap[curr_idx] = ~0UL;
- alloc_bitmap[curr_idx] |= (1UL<<end_off)-1;
- }
-}
-
-
-static void map_free(unsigned long first_page, unsigned long nr_pages)
-{
- unsigned long start_off, end_off, curr_idx, end_idx;
-
- curr_idx = first_page / PAGES_PER_MAPWORD;
- start_off = first_page & (PAGES_PER_MAPWORD-1);
- end_idx = (first_page + nr_pages) / PAGES_PER_MAPWORD;
- end_off = (first_page + nr_pages) & (PAGES_PER_MAPWORD-1);
-
- if ( curr_idx == end_idx )
- {
- alloc_bitmap[curr_idx] &= -(1UL<<end_off) | ((1UL<<start_off)-1);
- }
- else
- {
- alloc_bitmap[curr_idx] &= (1UL<<start_off)-1;
- while ( ++curr_idx != end_idx ) alloc_bitmap[curr_idx] = 0;
- alloc_bitmap[curr_idx] &= -(1UL<<end_off);
- }
-}
-
-
-
-/*************************
- * BINARY BUDDY ALLOCATOR
- */
-
-typedef struct chunk_head_st chunk_head_t;
-typedef struct chunk_tail_st chunk_tail_t;
-
-struct chunk_head_st {
- chunk_head_t *next;
- chunk_head_t **pprev;
- int level;
-};
-
-struct chunk_tail_st {
- int level;
-};
-
-/* Linked lists of free chunks of different powers-of-two in size. */
-#define FREELIST_SIZE ((sizeof(void*)<<3)-PAGE_SHIFT)
-static chunk_head_t *free_head[FREELIST_SIZE];
-static chunk_head_t free_tail[FREELIST_SIZE];
-#define FREELIST_EMPTY(_l) ((_l)->next == NULL)
-
-#define round_pgdown(_p) ((_p)&PAGE_MASK)
-#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
-
-#ifdef MM_DEBUG
-/*
- * Prints allocation[0/1] for @nr_pages, starting at @start
- * address (virtual).
- */
-USED static void print_allocation(void *start, int nr_pages)
-{
- unsigned long pfn_start = virt_to_pfn(start);
- int count;
- for(count = 0; count < nr_pages; count++)
- if(allocated_in_map(pfn_start + count)) printk("1");
- else printk("0");
-
- printk("\n");
-}
-
-/*
- * Prints chunks (making them with letters) for @nr_pages starting
- * at @start (virtual).
- */
-USED static void print_chunks(void *start, int nr_pages)
-{
- char chunks[1001], current='A';
- int order, count;
- chunk_head_t *head;
- unsigned long pfn_start = virt_to_pfn(start);
-
- memset(chunks, (int)'_', 1000);
- if(nr_pages > 1000)
- {
- DEBUG("Can only pring 1000 pages. Increase buffer size.");
- }
-
- for(order=0; order < FREELIST_SIZE; order++)
- {
- head = free_head[order];
- while(!FREELIST_EMPTY(head))
- {
- for(count = 0; count < 1UL<< head->level; count++)
- {
- if(count + virt_to_pfn(head) - pfn_start < 1000)
- chunks[count + virt_to_pfn(head) - pfn_start] = current;
- }
- head = head->next;
- current++;
- }
- }
- chunks[nr_pages] = '\0';
- printk("%s\n", chunks);
-}
-#endif
-
-
-/*
- * Initialise allocator, placing addresses [@min,@max] in free pool.
- * @min and @max are PHYSICAL addresses.
- */
-static void init_page_allocator(unsigned long min, unsigned long max)
-{
- int i;
- unsigned long range, bitmap_size;
- chunk_head_t *ch;
- chunk_tail_t *ct;
- for ( i = 0; i < FREELIST_SIZE; i++ )
- {
- free_head[i] = &free_tail[i];
- free_tail[i].pprev = &free_head[i];
- free_tail[i].next = NULL;
- }
-
- min = round_pgup (min);
- max = round_pgdown(max);
-
- /* Allocate space for the allocation bitmap. */
- bitmap_size = (max+1) >> (PAGE_SHIFT+3);
- bitmap_size = round_pgup(bitmap_size);
- alloc_bitmap = (unsigned long *)to_virt(min);
- min += bitmap_size;
- range = max - min;
-
- /* All allocated by default. */
- memset(alloc_bitmap, ~0, bitmap_size);
- /* Free up the memory we've been given to play with. */
- map_free(PHYS_PFN(min), range>>PAGE_SHIFT);
-
- /* The buddy lists are addressed in high memory. */
- min = (unsigned long) to_virt(min);
- max = (unsigned long) to_virt(max);
-
- while ( range != 0 )
- {
- /*
- * Next chunk is limited by alignment of min, but also
- * must not be bigger than remaining range.
- */
- for ( i = PAGE_SHIFT; (1UL<<(i+1)) <= range; i++ )
- if ( min & (1UL<<i) ) break;
-
-
- ch = (chunk_head_t *)min;
- min += (1UL<<i);
- range -= (1UL<<i);
- ct = (chunk_tail_t *)min-1;
- i -= PAGE_SHIFT;
- ch->level = i;
- ch->next = free_head[i];
- ch->pprev = &free_head[i];
- ch->next->pprev = &ch->next;
- free_head[i] = ch;
- ct->level = i;
- }
-}
-
-
-/* Allocate 2^@order contiguous pages. Returns a VIRTUAL address. */
-unsigned long alloc_pages(int order)
-{
- int i;
- chunk_head_t *alloc_ch, *spare_ch;
- chunk_tail_t *spare_ct;
-
-
- /* Find smallest order which can satisfy the request. */
- for ( i = order; i < FREELIST_SIZE; i++ ) {
- if ( !FREELIST_EMPTY(free_head[i]) )
- break;
- }
-
- if ( i == FREELIST_SIZE ) goto no_memory;
-
- /* Unlink a chunk. */
- alloc_ch = free_head[i];
- free_head[i] = alloc_ch->next;
- alloc_ch->next->pprev = alloc_ch->pprev;
-
- /* We may have to break the chunk a number of times. */
- while ( i != order )
- {
- /* Split into two equal parts. */
- i--;
- spare_ch = (chunk_head_t *)((char *)alloc_ch + (1UL<<(i+PAGE_SHIFT)));
- spare_ct = (chunk_tail_t *)((char *)spare_ch + (1UL<<(i+PAGE_SHIFT)))-1;
-
- /* Create new header for spare chunk. */
- spare_ch->level = i;
- spare_ch->next = free_head[i];
- spare_ch->pprev = &free_head[i];
- spare_ct->level = i;
-
- /* Link in the spare chunk. */
- spare_ch->next->pprev = &spare_ch->next;
- free_head[i] = spare_ch;
- }
-
- map_alloc(PHYS_PFN(to_phys(alloc_ch)), 1UL<<order);
-
- return((unsigned long)alloc_ch);
-
- no_memory:
-
- printk("Cannot handle page request order %d!\n", order);
-
- return 0;
-}
-
-void free_pages(void *pointer, int order)
-{
- chunk_head_t *freed_ch, *to_merge_ch;
- chunk_tail_t *freed_ct;
- unsigned long mask;
-
- /* First free the chunk */
- map_free(virt_to_pfn(pointer), 1UL << order);
-
- /* Create free chunk */
- freed_ch = (chunk_head_t *)pointer;
- freed_ct = (chunk_tail_t *)((char *)pointer + (1UL<<(order + PAGE_SHIFT)))-1;
-
- /* Now, possibly we can conseal chunks together */
- while(order < FREELIST_SIZE)
- {
- mask = 1UL << (order + PAGE_SHIFT);
- if((unsigned long)freed_ch & mask)
- {
- to_merge_ch = (chunk_head_t *)((char *)freed_ch - mask);
- if(allocated_in_map(virt_to_pfn(to_merge_ch)) ||
- to_merge_ch->level != order)
- break;
-
- /* Merge with predecessor */
- freed_ch = to_merge_ch;
- }
- else
- {
- to_merge_ch = (chunk_head_t *)((char *)freed_ch + mask);
- if(allocated_in_map(virt_to_pfn(to_merge_ch)) ||
- to_merge_ch->level != order)
- break;
-
- /* Merge with successor */
- freed_ct = (chunk_tail_t *)((char *)to_merge_ch + mask) - 1;
- }
-
- /* We are commited to merging, unlink the chunk */
- *(to_merge_ch->pprev) = to_merge_ch->next;
- to_merge_ch->next->pprev = to_merge_ch->pprev;
-
- order++;
- }
-
- /* Link the new chunk */
- freed_ch->level = order;
- freed_ch->next = free_head[order];
- freed_ch->pprev = &free_head[order];
- freed_ct->level = order;
-
- freed_ch->next->pprev = &freed_ch->next;
- free_head[order] = freed_ch;
-
-}
-
-int free_physical_pages(xen_pfn_t *mfns, int n)
-{
- struct xen_memory_reservation reservation;
-
- set_xen_guest_handle(reservation.extent_start, mfns);
- reservation.nr_extents = n;
- reservation.extent_order = 0;
- reservation.domid = DOMID_SELF;
- return HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
-}
-
-#ifdef HAVE_LIBC
-void *sbrk(ptrdiff_t increment)
-{
- unsigned long old_brk = brk;
- unsigned long new_brk = old_brk + increment;
-
- if (new_brk > heap_end) {
- printk("Heap exhausted: %p + %lx = %p > %p\n", old_brk, increment, new_brk, heap_end);
- return NULL;
- }
-
- if (new_brk > heap_mapped) {
- unsigned long n = (new_brk - heap_mapped + PAGE_SIZE - 1) / PAGE_SIZE;
- do_map_zero(heap_mapped, n);
- heap_mapped += n * PAGE_SIZE;
- }
-
- brk = new_brk;
-
- return (void *) old_brk;
-}
-#endif
-
-
-
-void init_mm(void)
-{
-
- unsigned long start_pfn, max_pfn;
-
- printk("MM: Init\n");
-
- arch_init_mm(&start_pfn, &max_pfn);
- /*
- * now we can initialise the page allocator
- */
- printk("MM: Initialise page allocator for %lx(%lx)-%lx(%lx)\n",
- (u_long)to_virt(PFN_PHYS(start_pfn)), (u_long)PFN_PHYS(start_pfn),
- (u_long)to_virt(PFN_PHYS(max_pfn)), (u_long)PFN_PHYS(max_pfn));
- init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn));
- printk("MM: done\n");
-
- arch_init_p2m(max_pfn);
-
- arch_init_demand_mapping_area(max_pfn);
-}
-
-void fini_mm(void)
-{
-}
-
-void sanity_check(void)
-{
- int x;
- chunk_head_t *head;
-
- for (x = 0; x < FREELIST_SIZE; x++) {
- for (head = free_head[x]; !FREELIST_EMPTY(head); head = head->next) {
- ASSERT(!allocated_in_map(virt_to_pfn(head)));
- if (head->next)
- ASSERT(head->next->pprev == &head->next);
- }
- if (free_head[x]) {
- ASSERT(free_head[x]->pprev == &free_head[x]);
- }
- }
-}
+++ /dev/null
-/* Minimal network driver for Mini-OS.
- * Copyright (c) 2006-2007 Jacob Gorm Hansen, University of Copenhagen.
- * Based on netfront.c from Xen Linux.
- *
- * Does not handle fragments or extras.
- */
-
-#include <mini-os/os.h>
-#include <mini-os/xenbus.h>
-#include <mini-os/events.h>
-#include <errno.h>
-#include <xen/io/netif.h>
-#include <mini-os/gnttab.h>
-#include <mini-os/xmalloc.h>
-#include <mini-os/time.h>
-#include <mini-os/netfront.h>
-#include <mini-os/lib.h>
-#include <mini-os/semaphore.h>
-
-DECLARE_WAIT_QUEUE_HEAD(netfront_queue);
-
-#ifdef HAVE_LIBC
-#define NETIF_SELECT_RX ((void*)-1)
-#endif
-
-
-
-#define NET_TX_RING_SIZE __CONST_RING_SIZE(netif_tx, PAGE_SIZE)
-#define NET_RX_RING_SIZE __CONST_RING_SIZE(netif_rx, PAGE_SIZE)
-#define GRANT_INVALID_REF 0
-
-
-struct net_buffer {
- void* page;
- grant_ref_t gref;
-};
-
-struct netfront_dev {
- domid_t dom;
-
- unsigned short tx_freelist[NET_TX_RING_SIZE + 1];
- struct semaphore tx_sem;
-
- struct net_buffer rx_buffers[NET_RX_RING_SIZE];
- struct net_buffer tx_buffers[NET_TX_RING_SIZE];
-
- struct netif_tx_front_ring tx;
- struct netif_rx_front_ring rx;
- grant_ref_t tx_ring_ref;
- grant_ref_t rx_ring_ref;
- evtchn_port_t evtchn;
-
- char *nodename;
- char *backend;
- char *mac;
-
- xenbus_event_queue events;
-
-#ifdef HAVE_LIBC
- int fd;
- unsigned char *data;
- size_t len;
- size_t rlen;
-#endif
-
- void (*netif_rx)(unsigned char* data, int len);
-};
-
-void init_rx_buffers(struct netfront_dev *dev);
-
-static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist)
-{
- freelist[id + 1] = freelist[0];
- freelist[0] = id;
-}
-
-static inline unsigned short get_id_from_freelist(unsigned short* freelist)
-{
- unsigned int id = freelist[0];
- freelist[0] = freelist[id + 1];
- return id;
-}
-
-__attribute__((weak)) void netif_rx(unsigned char* data,int len)
-{
- printk("%d bytes incoming at %p\n",len,data);
-}
-
-__attribute__((weak)) void net_app_main(void*si,unsigned char*mac) {}
-
-static inline int xennet_rxidx(RING_IDX idx)
-{
- return idx & (NET_RX_RING_SIZE - 1);
-}
-
-void network_rx(struct netfront_dev *dev)
-{
- RING_IDX rp,cons,req_prod;
- int nr_consumed, more, i, notify;
-#ifdef HAVE_LIBC
- int some;
-#endif
-
- nr_consumed = 0;
-moretodo:
- rp = dev->rx.sring->rsp_prod;
- rmb(); /* Ensure we see queued responses up to 'rp'. */
-
-#ifdef HAVE_LIBC
- some = 0;
-#endif
- for (cons = dev->rx.rsp_cons; cons != rp; nr_consumed++, cons++)
- {
- struct net_buffer* buf;
- unsigned char* page;
- int id;
-
- struct netif_rx_response *rx = RING_GET_RESPONSE(&dev->rx, cons);
-
- id = rx->id;
- BUG_ON(id >= NET_RX_RING_SIZE);
-
- buf = &dev->rx_buffers[id];
- page = (unsigned char*)buf->page;
- gnttab_end_access(buf->gref);
-
- if (rx->status > NETIF_RSP_NULL)
- {
-#ifdef HAVE_LIBC
- if (dev->netif_rx == NETIF_SELECT_RX) {
- int len = rx->status;
- ASSERT(current == main_thread);
- if (len > dev->len)
- len = dev->len;
- memcpy(dev->data, page+rx->offset, len);
- dev->rlen = len;
- some = 1;
- break;
- } else
-#endif
- dev->netif_rx(page+rx->offset,rx->status);
- }
- }
- dev->rx.rsp_cons=cons;
-
- RING_FINAL_CHECK_FOR_RESPONSES(&dev->rx,more);
-#ifdef HAVE_LIBC
- if(more && !some) goto moretodo;
-#else
- if(more) goto moretodo;
-#endif
-
- req_prod = dev->rx.req_prod_pvt;
-
- for(i=0; i<nr_consumed; i++)
- {
- int id = xennet_rxidx(req_prod + i);
- netif_rx_request_t *req = RING_GET_REQUEST(&dev->rx, req_prod + i);
- struct net_buffer* buf = &dev->rx_buffers[id];
- void* page = buf->page;
-
- /* We are sure to have free gnttab entries since they got released above */
- buf->gref = req->gref =
- gnttab_grant_access(dev->dom,virt_to_mfn(page),0);
-
- req->id = id;
- }
-
- wmb();
-
- dev->rx.req_prod_pvt = req_prod + i;
-
- RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->rx, notify);
- if (notify)
- notify_remote_via_evtchn(dev->evtchn);
-
-}
-
-void network_tx_buf_gc(struct netfront_dev *dev)
-{
-
-
- RING_IDX cons, prod;
- unsigned short id;
-
- do {
- prod = dev->tx.sring->rsp_prod;
- rmb(); /* Ensure we see responses up to 'rp'. */
-
- for (cons = dev->tx.rsp_cons; cons != prod; cons++)
- {
- struct netif_tx_response *txrsp;
- struct net_buffer *buf;
-
- txrsp = RING_GET_RESPONSE(&dev->tx, cons);
- if (txrsp->status == NETIF_RSP_NULL)
- continue;
-
- if (txrsp->status == NETIF_RSP_ERROR)
- printk("packet error\n");
-
- id = txrsp->id;
- BUG_ON(id >= NET_TX_RING_SIZE);
- buf = &dev->tx_buffers[id];
- gnttab_end_access(buf->gref);
- buf->gref=GRANT_INVALID_REF;
-
- add_id_to_freelist(id,dev->tx_freelist);
- up(&dev->tx_sem);
- }
-
- dev->tx.rsp_cons = prod;
-
- /*
- * Set a new event, then check for race with update of tx_cons.
- * Note that it is essential to schedule a callback, no matter
- * how few tx_buffers are pending. Even if there is space in the
- * transmit ring, higher layers may be blocked because too much
- * data is outstanding: in such cases notification from Xen is
- * likely to be the only kick that we'll get.
- */
- dev->tx.sring->rsp_event =
- prod + ((dev->tx.sring->req_prod - prod) >> 1) + 1;
- mb();
- } while ((cons == prod) && (prod != dev->tx.sring->rsp_prod));
-
-
-}
-
-void netfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
-{
- int flags;
- struct netfront_dev *dev = data;
-
- local_irq_save(flags);
-
- network_tx_buf_gc(dev);
- network_rx(dev);
-
- local_irq_restore(flags);
-}
-
-#ifdef HAVE_LIBC
-void netfront_select_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
-{
- int flags;
- struct netfront_dev *dev = data;
- int fd = dev->fd;
-
- local_irq_save(flags);
- network_tx_buf_gc(dev);
- local_irq_restore(flags);
-
- if (fd != -1)
- files[fd].read = 1;
- wake_up(&netfront_queue);
-}
-#endif
-
-static void free_netfront(struct netfront_dev *dev)
-{
- int i;
-
- for(i=0;i<NET_TX_RING_SIZE;i++)
- down(&dev->tx_sem);
-
- mask_evtchn(dev->evtchn);
-
- free(dev->mac);
- free(dev->backend);
-
- gnttab_end_access(dev->rx_ring_ref);
- gnttab_end_access(dev->tx_ring_ref);
-
- free_page(dev->rx.sring);
- free_page(dev->tx.sring);
-
- unbind_evtchn(dev->evtchn);
-
- for(i=0;i<NET_RX_RING_SIZE;i++) {
- gnttab_end_access(dev->rx_buffers[i].gref);
- free_page(dev->rx_buffers[i].page);
- }
-
- for(i=0;i<NET_TX_RING_SIZE;i++)
- if (dev->tx_buffers[i].page)
- free_page(dev->tx_buffers[i].page);
-
- free(dev->nodename);
- free(dev);
-}
-
-struct netfront_dev *init_netfront(char *_nodename, void (*thenetif_rx)(unsigned char* data, int len), unsigned char rawmac[6], char **ip)
-{
- xenbus_transaction_t xbt;
- char* err;
- char* message=NULL;
- struct netif_tx_sring *txs;
- struct netif_rx_sring *rxs;
- int retry=0;
- int i;
- char* msg = NULL;
- char nodename[256];
- char path[256];
- struct netfront_dev *dev;
- static int netfrontends = 0;
-
- if (!_nodename)
- snprintf(nodename, sizeof(nodename), "device/vif/%d", netfrontends);
- else {
- strncpy(nodename, _nodename, sizeof(nodename) - 1);
- nodename[sizeof(nodename) - 1] = 0;
- }
- netfrontends++;
-
- if (!thenetif_rx)
- thenetif_rx = netif_rx;
-
- printk("************************ NETFRONT for %s **********\n\n\n", nodename);
-
- dev = malloc(sizeof(*dev));
- memset(dev, 0, sizeof(*dev));
- dev->nodename = strdup(nodename);
-#ifdef HAVE_LIBC
- dev->fd = -1;
-#endif
-
- printk("net TX ring size %d\n", NET_TX_RING_SIZE);
- printk("net RX ring size %d\n", NET_RX_RING_SIZE);
- init_SEMAPHORE(&dev->tx_sem, NET_TX_RING_SIZE);
- for(i=0;i<NET_TX_RING_SIZE;i++)
- {
- add_id_to_freelist(i,dev->tx_freelist);
- dev->tx_buffers[i].page = NULL;
- }
-
- for(i=0;i<NET_RX_RING_SIZE;i++)
- {
- /* TODO: that's a lot of memory */
- dev->rx_buffers[i].page = (char*)alloc_page();
- }
-
- snprintf(path, sizeof(path), "%s/backend-id", nodename);
- dev->dom = xenbus_read_integer(path);
-#ifdef HAVE_LIBC
- if (thenetif_rx == NETIF_SELECT_RX)
- evtchn_alloc_unbound(dev->dom, netfront_select_handler, dev, &dev->evtchn);
- else
-#endif
- evtchn_alloc_unbound(dev->dom, netfront_handler, dev, &dev->evtchn);
-
- txs = (struct netif_tx_sring *) alloc_page();
- rxs = (struct netif_rx_sring *) alloc_page();
- memset(txs,0,PAGE_SIZE);
- memset(rxs,0,PAGE_SIZE);
-
-
- SHARED_RING_INIT(txs);
- SHARED_RING_INIT(rxs);
- FRONT_RING_INIT(&dev->tx, txs, PAGE_SIZE);
- FRONT_RING_INIT(&dev->rx, rxs, PAGE_SIZE);
-
- dev->tx_ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(txs),0);
- dev->rx_ring_ref = gnttab_grant_access(dev->dom,virt_to_mfn(rxs),0);
-
- init_rx_buffers(dev);
-
- dev->netif_rx = thenetif_rx;
-
- dev->events = NULL;
-
-again:
- err = xenbus_transaction_start(&xbt);
- if (err) {
- printk("starting transaction\n");
- free(err);
- }
-
- err = xenbus_printf(xbt, nodename, "tx-ring-ref","%u",
- dev->tx_ring_ref);
- if (err) {
- message = "writing tx ring-ref";
- goto abort_transaction;
- }
- err = xenbus_printf(xbt, nodename, "rx-ring-ref","%u",
- dev->rx_ring_ref);
- if (err) {
- message = "writing rx ring-ref";
- goto abort_transaction;
- }
- err = xenbus_printf(xbt, nodename,
- "event-channel", "%u", dev->evtchn);
- if (err) {
- message = "writing event-channel";
- goto abort_transaction;
- }
-
- err = xenbus_printf(xbt, nodename, "request-rx-copy", "%u", 1);
-
- if (err) {
- message = "writing request-rx-copy";
- goto abort_transaction;
- }
-
- snprintf(path, sizeof(path), "%s/state", nodename);
- err = xenbus_switch_state(xbt, path, XenbusStateConnected);
- if (err) {
- message = "switching state";
- goto abort_transaction;
- }
-
- err = xenbus_transaction_end(xbt, 0, &retry);
- free(err);
- if (retry) {
- goto again;
- printk("completing transaction\n");
- }
-
- goto done;
-
-abort_transaction:
- free(err);
- err = xenbus_transaction_end(xbt, 1, &retry);
- printk("Abort transaction %s\n", message);
- goto error;
-
-done:
-
- snprintf(path, sizeof(path), "%s/backend", nodename);
- msg = xenbus_read(XBT_NIL, path, &dev->backend);
- snprintf(path, sizeof(path), "%s/mac", nodename);
- msg = xenbus_read(XBT_NIL, path, &dev->mac);
-
- if ((dev->backend == NULL) || (dev->mac == NULL)) {
- printk("%s: backend/mac failed\n", __func__);
- goto error;
- }
-
- printk("backend at %s\n",dev->backend);
- printk("mac is %s\n",dev->mac);
-
- {
- XenbusState state;
- char path[strlen(dev->backend) + strlen("/state") + 1];
- snprintf(path, sizeof(path), "%s/state", dev->backend);
-
- xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
-
- err = NULL;
- state = xenbus_read_integer(path);
- while (err == NULL && state < XenbusStateConnected)
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- if (state != XenbusStateConnected) {
- printk("backend not avalable, state=%d\n", state);
- xenbus_unwatch_path_token(XBT_NIL, path, path);
- goto error;
- }
-
- if (ip) {
- snprintf(path, sizeof(path), "%s/ip", dev->backend);
- xenbus_read(XBT_NIL, path, ip);
- }
- }
-
- printk("**************************\n");
-
- unmask_evtchn(dev->evtchn);
-
- /* Special conversion specifier 'hh' needed for __ia64__. Without
- this mini-os panics with 'Unaligned reference'. */
- if (rawmac)
- sscanf(dev->mac,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
- &rawmac[0],
- &rawmac[1],
- &rawmac[2],
- &rawmac[3],
- &rawmac[4],
- &rawmac[5]);
-
- return dev;
-error:
- free(msg);
- free(err);
- free_netfront(dev);
- return NULL;
-}
-
-#ifdef HAVE_LIBC
-int netfront_tap_open(char *nodename) {
- struct netfront_dev *dev;
-
- dev = init_netfront(nodename, NETIF_SELECT_RX, NULL, NULL);
- if (!dev) {
- printk("TAP open failed\n");
- errno = EIO;
- return -1;
- }
- dev->fd = alloc_fd(FTYPE_TAP);
- printk("tap_open(%s) -> %d\n", nodename, dev->fd);
- files[dev->fd].tap.dev = dev;
- return dev->fd;
-}
-#endif
-
-void shutdown_netfront(struct netfront_dev *dev)
-{
- char* err = NULL, *err2;
- XenbusState state;
-
- char path[strlen(dev->backend) + strlen("/state") + 1];
- char nodename[strlen(dev->nodename) + strlen("/request-rx-copy") + 1];
-
- printk("close network: backend at %s\n",dev->backend);
-
- snprintf(path, sizeof(path), "%s/state", dev->backend);
- snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
-
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
- printk("shutdown_netfront: error changing state to %d: %s\n",
- XenbusStateClosing, err);
- goto close;
- }
- state = xenbus_read_integer(path);
- while (err == NULL && state < XenbusStateClosing)
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- free(err);
-
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
- printk("shutdown_netfront: error changing state to %d: %s\n",
- XenbusStateClosed, err);
- goto close;
- }
- state = xenbus_read_integer(path);
- while (state < XenbusStateClosed) {
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- free(err);
- }
-
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
- printk("shutdown_netfront: error changing state to %d: %s\n",
- XenbusStateInitialising, err);
- goto close;
- }
- state = xenbus_read_integer(path);
- while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
-
-close:
- free(err);
- err2 = xenbus_unwatch_path_token(XBT_NIL, path, path);
- free(err2);
-
- snprintf(nodename, sizeof(nodename), "%s/tx-ring-ref", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
- snprintf(nodename, sizeof(nodename), "%s/rx-ring-ref", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
- snprintf(nodename, sizeof(nodename), "%s/event-channel", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
- snprintf(nodename, sizeof(nodename), "%s/request-rx-copy", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
-
- if (!err)
- free_netfront(dev);
-}
-
-
-void init_rx_buffers(struct netfront_dev *dev)
-{
- int i, requeue_idx;
- netif_rx_request_t *req;
- int notify;
-
- /* Rebuild the RX buffer freelist and the RX ring itself. */
- for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++)
- {
- struct net_buffer* buf = &dev->rx_buffers[requeue_idx];
- req = RING_GET_REQUEST(&dev->rx, requeue_idx);
-
- buf->gref = req->gref =
- gnttab_grant_access(dev->dom,virt_to_mfn(buf->page),0);
-
- req->id = requeue_idx;
-
- requeue_idx++;
- }
-
- dev->rx.req_prod_pvt = requeue_idx;
-
- RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->rx, notify);
-
- if (notify)
- notify_remote_via_evtchn(dev->evtchn);
-
- dev->rx.sring->rsp_event = dev->rx.rsp_cons + 1;
-}
-
-
-void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len)
-{
- int flags;
- struct netif_tx_request *tx;
- RING_IDX i;
- int notify;
- unsigned short id;
- struct net_buffer* buf;
- void* page;
-
- BUG_ON(len > PAGE_SIZE);
-
- down(&dev->tx_sem);
-
- local_irq_save(flags);
- id = get_id_from_freelist(dev->tx_freelist);
- local_irq_restore(flags);
-
- buf = &dev->tx_buffers[id];
- page = buf->page;
- if (!page)
- page = buf->page = (char*) alloc_page();
-
- i = dev->tx.req_prod_pvt;
- tx = RING_GET_REQUEST(&dev->tx, i);
-
- memcpy(page,data,len);
-
- buf->gref =
- tx->gref = gnttab_grant_access(dev->dom,virt_to_mfn(page),1);
-
- tx->offset=0;
- tx->size = len;
- tx->flags=0;
- tx->id = id;
- dev->tx.req_prod_pvt = i + 1;
-
- wmb();
-
- RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->tx, notify);
-
- if(notify) notify_remote_via_evtchn(dev->evtchn);
-
- local_irq_save(flags);
- network_tx_buf_gc(dev);
- local_irq_restore(flags);
-}
-
-#ifdef HAVE_LIBC
-ssize_t netfront_receive(struct netfront_dev *dev, unsigned char *data, size_t len)
-{
- unsigned long flags;
- int fd = dev->fd;
- ASSERT(current == main_thread);
-
- dev->rlen = 0;
- dev->data = data;
- dev->len = len;
-
- local_irq_save(flags);
- network_rx(dev);
- if (!dev->rlen && fd != -1)
- /* No data for us, make select stop returning */
- files[fd].read = 0;
- /* Before re-enabling the interrupts, in case a packet just arrived in the
- * meanwhile. */
- local_irq_restore(flags);
-
- dev->data = NULL;
- dev->len = 0;
-
- return dev->rlen;
-}
-#endif
+++ /dev/null
-/* Minimal PCI driver for Mini-OS.
- * Copyright (c) 2007-2008 Samuel Thibault.
- * Based on blkfront.c.
- */
-
-#include <string.h>
-#include <mini-os/os.h>
-#include <mini-os/lib.h>
-#include <mini-os/xenbus.h>
-#include <mini-os/events.h>
-#include <errno.h>
-#include <mini-os/gnttab.h>
-#include <mini-os/xmalloc.h>
-#include <mini-os/wait.h>
-#include <mini-os/pcifront.h>
-#include <mini-os/sched.h>
-
-#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
-
-DECLARE_WAIT_QUEUE_HEAD(pcifront_queue);
-static struct pcifront_dev *pcidev;
-
-struct pcifront_dev {
- domid_t dom;
-
- struct xen_pci_sharedinfo *info;
- grant_ref_t info_ref;
- evtchn_port_t evtchn;
-
- char *nodename;
- char *backend;
-
- xenbus_event_queue events;
-};
-
-void pcifront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
-{
- wake_up(&pcifront_queue);
-}
-
-static void free_pcifront(struct pcifront_dev *dev)
-{
- if (!dev)
- dev = pcidev;
-
- mask_evtchn(dev->evtchn);
-
- gnttab_end_access(dev->info_ref);
- free_page(dev->info);
-
- unbind_evtchn(dev->evtchn);
-
- free(dev->backend);
- free(dev->nodename);
- free(dev);
-}
-
-void pcifront_watches(void *opaque)
-{
- XenbusState state;
- char *err = NULL, *msg = NULL;
- char *be_path, *be_state;
- char* nodename = opaque ? opaque : "device/pci/0";
- char path[strlen(nodename) + 9];
- char fe_state[strlen(nodename) + 7];
- xenbus_event_queue events = NULL;
-
- snprintf(path, sizeof(path), "%s/backend", nodename);
- snprintf(fe_state, sizeof(fe_state), "%s/state", nodename);
-
- while (1) {
- printk("pcifront_watches: waiting for backend path to appear %s\n", path);
- xenbus_watch_path_token(XBT_NIL, path, path, &events);
- while ((err = xenbus_read(XBT_NIL, path, &be_path)) != NULL) {
- free(err);
- xenbus_wait_for_watch(&events);
- }
- xenbus_unwatch_path_token(XBT_NIL, path, path);
- printk("pcifront_watches: waiting for backend to get into the right state %s\n", be_path);
- be_state = (char *) malloc(strlen(be_path) + 7);
- snprintf(be_state, strlen(be_path) + 7, "%s/state", be_path);
- xenbus_watch_path_token(XBT_NIL, be_state, be_state, &events);
- while ((err = xenbus_read(XBT_NIL, be_state, &msg)) != NULL || msg[0] > '4') {
- free(msg);
- free(err);
- xenbus_wait_for_watch(&events);
- }
- xenbus_unwatch_path_token(XBT_NIL, be_state, be_state);
- if (init_pcifront(NULL) == NULL) {
- free(be_state);
- free(be_path);
- continue;
- }
- xenbus_watch_path_token(XBT_NIL, be_state, be_state, &events);
- state = XenbusStateConnected;
- printk("pcifront_watches: waiting for backend events %s\n", be_state);
- while ((err = xenbus_wait_for_state_change(be_state, &state, &events)) == NULL &&
- (err = xenbus_read(XBT_NIL, pcidev->backend, &msg)) == NULL) {
- free(msg);
- printk("pcifront_watches: backend state changed: %s %d\n", be_state, state);
- if (state == XenbusStateReconfiguring) {
- printk("pcifront_watches: writing %s %d\n", fe_state, XenbusStateReconfiguring);
- if ((err = xenbus_switch_state(XBT_NIL, fe_state, XenbusStateReconfiguring)) != NULL) {
- printk("pcifront_watches: error changing state to %d: %s\n",
- XenbusStateReconfiguring, err);
- if (!strcmp(err, "ENOENT")) {
- xenbus_write(XBT_NIL, fe_state, "7");
- free(err);
- }
- }
- } else if (state == XenbusStateReconfigured) {
- printk("pcifront_watches: writing %s %d\n", fe_state, XenbusStateConnected);
- printk("pcifront_watches: changing state to %d\n", XenbusStateConnected);
- if ((err = xenbus_switch_state(XBT_NIL, fe_state, XenbusStateConnected)) != NULL) {
- printk("pcifront_watches: error changing state to %d: %s\n",
- XenbusStateConnected, err);
- if (!strcmp(err, "ENOENT")) {
- xenbus_write(XBT_NIL, fe_state, "4");
- free(err);
- }
- }
- } else if (state == XenbusStateClosing)
- break;
- }
- if (err) {
- printk("pcifront_watches: done waiting err=%s\n", err);
- free(err);
- } else
- printk("pcifront_watches: done waiting\n");
- err = xenbus_unwatch_path_token(XBT_NIL, be_state, be_state);
- shutdown_pcifront(pcidev);
- free(be_state);
- free(be_path);
- free(err);
- pcidev = NULL;
- }
-
- xenbus_unwatch_path_token(XBT_NIL, path, path);
-}
-
-struct pcifront_dev *init_pcifront(char *_nodename)
-{
- xenbus_transaction_t xbt;
- char* err;
- char* message=NULL;
- int retry=0;
- char* msg = NULL;
- char* nodename = _nodename ? _nodename : "device/pci/0";
- int dom;
-
- struct pcifront_dev *dev;
-
- char path[strlen(nodename) + strlen("/backend-id") + 1];
-
- if (!_nodename && pcidev)
- return pcidev;
-
- printk("******************* PCIFRONT for %s **********\n\n\n", nodename);
-
- snprintf(path, sizeof(path), "%s/backend-id", nodename);
- dom = xenbus_read_integer(path);
- if (dom == -1) {
- printk("no backend\n");
- return NULL;
- }
-
- dev = malloc(sizeof(*dev));
- memset(dev, 0, sizeof(*dev));
- dev->nodename = strdup(nodename);
- dev->dom = dom;
-
- evtchn_alloc_unbound(dev->dom, pcifront_handler, dev, &dev->evtchn);
-
- dev->info = (struct xen_pci_sharedinfo*) alloc_page();
- memset(dev->info,0,PAGE_SIZE);
-
- dev->info_ref = gnttab_grant_access(dev->dom,virt_to_mfn(dev->info),0);
-
- dev->events = NULL;
-
-again:
- err = xenbus_transaction_start(&xbt);
- if (err) {
- printk("starting transaction\n");
- free(err);
- }
-
- err = xenbus_printf(xbt, nodename, "pci-op-ref","%u",
- dev->info_ref);
- if (err) {
- message = "writing pci-op-ref";
- goto abort_transaction;
- }
- err = xenbus_printf(xbt, nodename,
- "event-channel", "%u", dev->evtchn);
- if (err) {
- message = "writing event-channel";
- goto abort_transaction;
- }
- err = xenbus_printf(xbt, nodename,
- "magic", XEN_PCI_MAGIC);
- if (err) {
- message = "writing magic";
- goto abort_transaction;
- }
-
- snprintf(path, sizeof(path), "%s/state", nodename);
- err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
- if (err) {
- message = "switching state";
- goto abort_transaction;
- }
-
- err = xenbus_transaction_end(xbt, 0, &retry);
- free(err);
- if (retry) {
- goto again;
- printk("completing transaction\n");
- }
-
- goto done;
-
-abort_transaction:
- free(err);
- err = xenbus_transaction_end(xbt, 1, &retry);
- printk("Abort transaction %s\n", message);
- goto error;
-
-done:
-
- snprintf(path, sizeof(path), "%s/backend", nodename);
- msg = xenbus_read(XBT_NIL, path, &dev->backend);
- if (msg) {
- printk("Error %s when reading the backend path %s\n", msg, path);
- goto error;
- }
-
- printk("backend at %s\n", dev->backend);
-
- {
- char path[strlen(dev->backend) + strlen("/state") + 1];
- char frontpath[strlen(nodename) + strlen("/state") + 1];
- XenbusState state;
- snprintf(path, sizeof(path), "%s/state", dev->backend);
-
- xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
-
- err = NULL;
- state = xenbus_read_integer(path);
- while (err == NULL && state < XenbusStateConnected)
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- if (state != XenbusStateConnected) {
- printk("backend not avalable, state=%d\n", state);
- free(err);
- err = xenbus_unwatch_path_token(XBT_NIL, path, path);
- goto error;
- }
-
- snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
- if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
- != NULL) {
- printk("error switching state %s\n", err);
- free(err);
- err = xenbus_unwatch_path_token(XBT_NIL, path, path);
- goto error;
- }
- }
- unmask_evtchn(dev->evtchn);
-
- printk("**************************\n");
-
- if (!_nodename)
- pcidev = dev;
-
- return dev;
-
-error:
- free(msg);
- free(err);
- free_pcifront(dev);
- return NULL;
-}
-
-void pcifront_scan(struct pcifront_dev *dev, void (*func)(unsigned int domain, unsigned int bus, unsigned slot, unsigned int fun))
-{
- char *path;
- int i, n, len;
- char *s, *msg = NULL;
- unsigned int domain, bus, slot, fun;
-
- if (!dev)
- dev = pcidev;
- if (!dev) {
- printk("pcifront_scan: device or bus\n");
- return;
- }
-
- len = strlen(dev->backend) + 1 + 5 + 10 + 1;
- path = (char *) malloc(len);
- snprintf(path, len, "%s/num_devs", dev->backend);
- n = xenbus_read_integer(path);
-
- for (i = 0; i < n; i++) {
- snprintf(path, len, "%s/dev-%d", dev->backend, i);
- msg = xenbus_read(XBT_NIL, path, &s);
- if (msg) {
- printk("Error %s when reading the PCI root name at %s\n", msg, path);
- free(msg);
- continue;
- }
-
- if (sscanf(s, "%x:%x:%x.%x", &domain, &bus, &slot, &fun) != 4) {
- printk("\"%s\" does not look like a PCI device address\n", s);
- free(s);
- continue;
- }
- free(s);
-
- if (func)
- func(domain, bus, slot, fun);
- }
- free(path);
-}
-
-void shutdown_pcifront(struct pcifront_dev *dev)
-{
- char* err = NULL, *err2;
- XenbusState state;
-
- char path[strlen(dev->backend) + strlen("/state") + 1];
- char nodename[strlen(dev->nodename) + strlen("/event-channel") + 1];
-
- printk("close pci: backend at %s\n",dev->backend);
-
- snprintf(path, sizeof(path), "%s/state", dev->backend);
- snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
- printk("shutdown_pcifront: error changing state to %d: %s\n",
- XenbusStateClosing, err);
- goto close_pcifront;
- }
- state = xenbus_read_integer(path);
- while (err == NULL && state < XenbusStateClosing)
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- free(err);
-
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
- printk("shutdown_pcifront: error changing state to %d: %s\n",
- XenbusStateClosed, err);
- goto close_pcifront;
- }
- state = xenbus_read_integer(path);
- while (state < XenbusStateClosed) {
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
- free(err);
- }
-
- if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
- printk("shutdown_pcifront: error changing state to %d: %s\n",
- XenbusStateInitialising, err);
- goto close_pcifront;
- }
- state = xenbus_read_integer(path);
- while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
- err = xenbus_wait_for_state_change(path, &state, &dev->events);
-
-close_pcifront:
- free(err);
- err2 = xenbus_unwatch_path_token(XBT_NIL, path, path);
- free(err2);
-
- snprintf(nodename, sizeof(nodename), "%s/info-ref", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
- snprintf(nodename, sizeof(nodename), "%s/event-channel", dev->nodename);
- err2 = xenbus_rm(XBT_NIL, nodename);
- free(err2);
-
- if (!err)
- free_pcifront(dev);
-}
-
-int pcifront_physical_to_virtual (struct pcifront_dev *dev,
- unsigned int *dom,
- unsigned int *bus,
- unsigned int *slot,
- unsigned int *fun)
-{
- /* FIXME: the buffer sizing is a little lazy here. 10 extra bytes
- should be enough to hold the paths we need to construct, even
- if the number of devices is large */
- char path[strlen(dev->backend) + strlen("/num_devs") + 10 + 1];
- int i, n;
- char *s, *msg = NULL;
- unsigned int dom1, bus1, slot1, fun1;
-
- if (!dev)
- dev = pcidev;
-
- snprintf(path, sizeof(path), "%s/num_devs", dev->backend);
- n = xenbus_read_integer(path);
-
- for (i = 0; i < n; i++) {
- snprintf(path, sizeof(path), "%s/dev-%d", dev->backend, i);
- msg = xenbus_read(XBT_NIL, path, &s);
- if (msg) {
- printk("Error %s when reading the PCI root name at %s\n", msg, path);
- free(msg);
- continue;
- }
-
- if (sscanf(s, "%x:%x:%x.%x", &dom1, &bus1, &slot1, &fun1) != 4) {
- printk("\"%s\" does not look like a PCI device address\n", s);
- free(s);
- continue;
- }
- free(s);
-
- if (dom1 == *dom && bus1 == *bus && slot1 == *slot && fun1 == *fun) {
- snprintf(path, sizeof(path), "%s/vdev-%d", dev->backend, i);
- msg = xenbus_read(XBT_NIL, path, &s);
- if (msg) {
- printk("Error %s when reading the PCI root name at %s\n", msg, path);
- continue;
- }
-
- if (sscanf(s, "%x:%x:%x.%x", dom, bus, slot, fun) != 4) {
- printk("\"%s\" does not look like a PCI device address\n", s);
- free(s);
- continue;
- }
- free(s);
-
- return 0;
- }
- }
- return -1;
-}
-
-void pcifront_op(struct pcifront_dev *dev, struct xen_pci_op *op)
-{
- if (!dev)
- dev = pcidev;
- dev->info->op = *op;
- /* Make sure info is written before the flag */
- wmb();
- set_bit(_XEN_PCIF_active, (void*) &dev->info->flags);
- notify_remote_via_evtchn(dev->evtchn);
-
- wait_event(pcifront_queue, !test_bit(_XEN_PCIF_active, (void*) &dev->info->flags));
-
- /* Make sure flag is read before info */
- rmb();
- *op = dev->info->op;
-}
-
-int pcifront_conf_read(struct pcifront_dev *dev,
- unsigned int dom,
- unsigned int bus, unsigned int slot, unsigned int fun,
- unsigned int off, unsigned int size, unsigned int *val)
-{
- struct xen_pci_op op;
-
- if (!dev)
- dev = pcidev;
- if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
- return XEN_PCI_ERR_dev_not_found;
- memset(&op, 0, sizeof(op));
-
- op.cmd = XEN_PCI_OP_conf_read;
- op.domain = dom;
- op.bus = bus;
- op.devfn = PCI_DEVFN(slot, fun);
- op.offset = off;
- op.size = size;
-
- pcifront_op(dev, &op);
-
- if (op.err)
- return op.err;
-
- *val = op.value;
-
- return 0;
-}
-
-int pcifront_conf_write(struct pcifront_dev *dev,
- unsigned int dom,
- unsigned int bus, unsigned int slot, unsigned int fun,
- unsigned int off, unsigned int size, unsigned int val)
-{
- struct xen_pci_op op;
-
- if (!dev)
- dev = pcidev;
- if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
- return XEN_PCI_ERR_dev_not_found;
- memset(&op, 0, sizeof(op));
-
- op.cmd = XEN_PCI_OP_conf_write;
- op.domain = dom;
- op.bus = bus;
- op.devfn = PCI_DEVFN(slot, fun);
- op.offset = off;
- op.size = size;
-
- op.value = val;
-
- pcifront_op(dev, &op);
-
- return op.err;
-}
-
-int pcifront_enable_msi(struct pcifront_dev *dev,
- unsigned int dom,
- unsigned int bus, unsigned int slot, unsigned int fun)
-{
- struct xen_pci_op op;
-
- if (!dev)
- dev = pcidev;
- if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
- return XEN_PCI_ERR_dev_not_found;
- memset(&op, 0, sizeof(op));
-
- op.cmd = XEN_PCI_OP_enable_msi;
- op.domain = dom;
- op.bus = bus;
- op.devfn = PCI_DEVFN(slot, fun);
-
- pcifront_op(dev, &op);
-
- if (op.err)
- return op.err;
- else
- return op.value;
-}
-
-int pcifront_disable_msi(struct pcifront_dev *dev,
- unsigned int dom,
- unsigned int bus, unsigned int slot, unsigned int fun)
-{
- struct xen_pci_op op;
-
- if (!dev)
- dev = pcidev;
- if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
- return XEN_PCI_ERR_dev_not_found;
- memset(&op, 0, sizeof(op));
-
- op.cmd = XEN_PCI_OP_disable_msi;
- op.domain = dom;
- op.bus = bus;
- op.devfn = PCI_DEVFN(slot, fun);
-
- pcifront_op(dev, &op);
-
- return op.err;
-}
-
-int pcifront_enable_msix(struct pcifront_dev *dev,
- unsigned int dom,
- unsigned int bus, unsigned int slot, unsigned int fun,
- struct xen_msix_entry *entries, int n)
-{
- struct xen_pci_op op;
-
- if (!dev)
- dev = pcidev;
- if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
- return XEN_PCI_ERR_dev_not_found;
- if (n > SH_INFO_MAX_VEC)
- return XEN_PCI_ERR_op_failed;
-
- memset(&op, 0, sizeof(op));
-
- op.cmd = XEN_PCI_OP_enable_msix;
- op.domain = dom;
- op.bus = bus;
- op.devfn = PCI_DEVFN(slot, fun);
- op.value = n;
-
- memcpy(op.msix_entries, entries, n * sizeof(*entries));
-
- pcifront_op(dev, &op);
-
- if (op.err)
- return op.err;
-
- memcpy(entries, op.msix_entries, n * sizeof(*entries));
-
- return 0;
-}
-
-
-int pcifront_disable_msix(struct pcifront_dev *dev,
- unsigned int dom,
- unsigned int bus, unsigned int slot, unsigned int fun)
-{
- struct xen_pci_op op;
-
- if (!dev)
- dev = pcidev;
- if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
- return XEN_PCI_ERR_dev_not_found;
- memset(&op, 0, sizeof(op));
-
- op.cmd = XEN_PCI_OP_disable_msix;
- op.domain = dom;
- op.bus = bus;
- op.devfn = PCI_DEVFN(slot, fun);
-
- pcifront_op(dev, &op);
-
- return op.err;
-}
+++ /dev/null
-/*
- ****************************************************************************
- * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
- ****************************************************************************
- *
- * File: sched.c
- * Author: Grzegorz Milos
- * Changes: Robert Kaiser
- *
- * Date: Aug 2005
- *
- * Environment: Xen Minimal OS
- * Description: simple scheduler for Mini-Os
- *
- * The scheduler is non-preemptive (cooperative), and schedules according
- * to Round Robin algorithm.
- *
- ****************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <mini-os/os.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/time.h>
-#include <mini-os/mm.h>
-#include <mini-os/types.h>
-#include <mini-os/lib.h>
-#include <mini-os/xmalloc.h>
-#include <mini-os/list.h>
-#include <mini-os/sched.h>
-#include <mini-os/semaphore.h>
-
-
-#ifdef SCHED_DEBUG
-#define DEBUG(_f, _a...) \
- printk("MINI_OS(file=sched.c, line=%d) " _f "\n", __LINE__, ## _a)
-#else
-#define DEBUG(_f, _a...) ((void)0)
-#endif
-
-MINIOS_TAILQ_HEAD(thread_list, struct thread);
-
-struct thread *idle_thread = NULL;
-static struct thread_list exited_threads = MINIOS_TAILQ_HEAD_INITIALIZER(exited_threads);
-static struct thread_list thread_list = MINIOS_TAILQ_HEAD_INITIALIZER(thread_list);
-static int threads_started;
-
-struct thread *main_thread;
-
-void inline print_runqueue(void)
-{
- struct thread *th;
- MINIOS_TAILQ_FOREACH(th, &thread_list, thread_list)
- {
- printk(" Thread \"%s\", runnable=%d\n", th->name, is_runnable(th));
- }
- printk("\n");
-}
-
-void schedule(void)
-{
- struct thread *prev, *next, *thread, *tmp;
- unsigned long flags;
-
- if (irqs_disabled()) {
- printk("Must not call schedule() with IRQs disabled\n");
- BUG();
- }
-
- prev = current;
- local_irq_save(flags);
-
- if (in_callback) {
- printk("Must not call schedule() from a callback\n");
- BUG();
- }
-
- do {
- /* Examine all threads.
- Find a runnable thread, but also wake up expired ones and find the
- time when the next timeout expires, else use 10 seconds. */
- s_time_t now = NOW();
- s_time_t min_wakeup_time = now + SECONDS(10);
- next = NULL;
- MINIOS_TAILQ_FOREACH_SAFE(thread, &thread_list, thread_list, tmp)
- {
- if (!is_runnable(thread) && thread->wakeup_time != 0LL)
- {
- if (thread->wakeup_time <= now)
- wake(thread);
- else if (thread->wakeup_time < min_wakeup_time)
- min_wakeup_time = thread->wakeup_time;
- }
- if(is_runnable(thread))
- {
- next = thread;
- /* Put this thread on the end of the list */
- MINIOS_TAILQ_REMOVE(&thread_list, thread, thread_list);
- MINIOS_TAILQ_INSERT_TAIL(&thread_list, thread, thread_list);
- break;
- }
- }
- if (next)
- break;
- /* block until the next timeout expires, or for 10 secs, whichever comes first */
- block_domain(min_wakeup_time);
- /* handle pending events if any */
- force_evtchn_callback();
- } while(1);
- local_irq_restore(flags);
- /* Interrupting the switch is equivalent to having the next thread
- inturrupted at the return instruction. And therefore at safe point. */
- if(prev != next) switch_threads(prev, next);
-
- MINIOS_TAILQ_FOREACH_SAFE(thread, &exited_threads, thread_list, tmp)
- {
- if(thread != prev)
- {
- MINIOS_TAILQ_REMOVE(&exited_threads, thread, thread_list);
- free_pages(thread->stack, STACK_SIZE_PAGE_ORDER);
- xfree(thread);
- }
- }
-}
-
-struct thread* create_thread(char *name, void (*function)(void *), void *data)
-{
- struct thread *thread;
- unsigned long flags;
- /* Call architecture specific setup. */
- thread = arch_create_thread(name, function, data);
- /* Not runable, not exited, not sleeping */
- thread->flags = 0;
- thread->wakeup_time = 0LL;
-#ifdef HAVE_LIBC
- _REENT_INIT_PTR((&thread->reent))
-#endif
- set_runnable(thread);
- local_irq_save(flags);
- MINIOS_TAILQ_INSERT_TAIL(&thread_list, thread, thread_list);
- local_irq_restore(flags);
- return thread;
-}
-
-#ifdef HAVE_LIBC
-static struct _reent callback_reent;
-struct _reent *__getreent(void)
-{
- struct _reent *_reent;
-
- if (!threads_started)
- _reent = _impure_ptr;
- else if (in_callback)
- _reent = &callback_reent;
- else
- _reent = &get_current()->reent;
-
-#ifndef NDEBUG
-#if defined(__x86_64__) || defined(__x86__)
- {
-#ifdef __x86_64__
- register unsigned long sp asm ("rsp");
-#else
- register unsigned long sp asm ("esp");
-#endif
- if ((sp & (STACK_SIZE-1)) < STACK_SIZE / 16) {
- static int overflowing;
- if (!overflowing) {
- overflowing = 1;
- printk("stack overflow\n");
- BUG();
- }
- }
- }
-#endif
-#else
-#error Not implemented yet
-#endif
- return _reent;
-}
-#endif
-
-void exit_thread(void)
-{
- unsigned long flags;
- struct thread *thread = current;
- printk("Thread \"%s\" exited.\n", thread->name);
- local_irq_save(flags);
- /* Remove from the thread list */
- MINIOS_TAILQ_REMOVE(&thread_list, thread, thread_list);
- clear_runnable(thread);
- /* Put onto exited list */
- MINIOS_TAILQ_INSERT_HEAD(&exited_threads, thread, thread_list);
- local_irq_restore(flags);
- /* Schedule will free the resources */
- while(1)
- {
- schedule();
- printk("schedule() returned! Trying again\n");
- }
-}
-
-void block(struct thread *thread)
-{
- thread->wakeup_time = 0LL;
- clear_runnable(thread);
-}
-
-void msleep(uint32_t millisecs)
-{
- struct thread *thread = get_current();
- thread->wakeup_time = NOW() + MILLISECS(millisecs);
- clear_runnable(thread);
- schedule();
-}
-
-void wake(struct thread *thread)
-{
- thread->wakeup_time = 0LL;
- set_runnable(thread);
-}
-
-void idle_thread_fn(void *unused)
-{
- threads_started = 1;
- while (1) {
- block(current);
- schedule();
- }
-}
-
-DECLARE_MUTEX(mutex);
-
-void th_f1(void *data)
-{
- struct timeval tv1, tv2;
-
- for(;;)
- {
- down(&mutex);
- printk("Thread \"%s\" got semaphore, runnable %d\n", current->name, is_runnable(current));
- schedule();
- printk("Thread \"%s\" releases the semaphore\n", current->name);
- up(&mutex);
-
-
- gettimeofday(&tv1, NULL);
- for(;;)
- {
- gettimeofday(&tv2, NULL);
- if(tv2.tv_sec - tv1.tv_sec > 2) break;
- }
-
-
- schedule();
- }
-}
-
-void th_f2(void *data)
-{
- for(;;)
- {
- printk("Thread OTHER executing, data 0x%lx\n", data);
- schedule();
- }
-}
-
-
-
-void init_sched(void)
-{
- printk("Initialising scheduler\n");
-
-#ifdef HAVE_LIBC
- _REENT_INIT_PTR((&callback_reent))
-#endif
- idle_thread = create_thread("Idle", idle_thread_fn, NULL);
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
+++ /dev/null
-/******************************************************************************
- * test.c
- *
- * Test code for all the various frontends; split from kernel.c
- *
- * Copyright (c) 2002-2003, K A Fraser & R Neugebauer
- * Copyright (c) 2005, Grzegorz Milos, Intel Research Cambridge
- * Copyright (c) 2006, Robert Kaiser, FH Wiesbaden
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <mini-os/os.h>
-#include <mini-os/hypervisor.h>
-#include <mini-os/mm.h>
-#include <mini-os/events.h>
-#include <mini-os/time.h>
-#include <mini-os/types.h>
-#include <mini-os/lib.h>
-#include <mini-os/sched.h>
-#include <mini-os/xenbus.h>
-#include <mini-os/gnttab.h>
-#include <mini-os/netfront.h>
-#include <mini-os/blkfront.h>
-#include <mini-os/fbfront.h>
-#include <mini-os/pcifront.h>
-#include <mini-os/xmalloc.h>
-#include <fcntl.h>
-#include <xen/features.h>
-#include <xen/version.h>
-
-#ifdef CONFIG_XENBUS
-static unsigned int do_shutdown = 0;
-static unsigned int shutdown_reason;
-static DECLARE_WAIT_QUEUE_HEAD(shutdown_queue);
-#endif
-
-#ifdef CONFIG_XENBUS
-void test_xenbus(void);
-
-static void xenbus_tester(void *p)
-{
- test_xenbus();
-}
-#endif
-
-#ifndef HAVE_LIBC
-/* Should be random enough for our uses */
-int rand(void)
-{
- static unsigned int previous;
- struct timeval tv;
- gettimeofday(&tv, NULL);
- previous += tv.tv_sec + tv.tv_usec;
- previous *= RAND_MIX;
- return previous;
-}
-#endif
-
-static void periodic_thread(void *p)
-{
- struct timeval tv;
- printk("Periodic thread started.\n");
- for(;;)
- {
- gettimeofday(&tv, NULL);
- printk("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec);
- msleep(1000);
- }
-}
-
-#ifdef CONFIG_NETFRONT
-static struct netfront_dev *net_dev;
-static struct semaphore net_sem = __SEMAPHORE_INITIALIZER(net_sem, 0);
-
-static void netfront_thread(void *p)
-{
- net_dev = init_netfront(NULL, NULL, NULL, NULL);
- up(&net_sem);
-}
-#endif
-
-#ifdef CONFIG_BLKFRONT
-static struct blkfront_dev *blk_dev;
-static struct blkfront_info blk_info;
-static uint64_t blk_size_read;
-static uint64_t blk_size_write;
-static struct semaphore blk_sem = __SEMAPHORE_INITIALIZER(blk_sem, 0);;
-
-struct blk_req {
- struct blkfront_aiocb aiocb;
- int rand_value;
- struct blk_req *next;
-};
-
-#ifdef BLKTEST_WRITE
-static struct blk_req *blk_to_read;
-#endif
-
-static struct blk_req *blk_alloc_req(uint64_t sector)
-{
- struct blk_req *req = xmalloc(struct blk_req);
- req->aiocb.aio_dev = blk_dev;
- req->aiocb.aio_buf = _xmalloc(blk_info.sector_size, blk_info.sector_size);
- req->aiocb.aio_nbytes = blk_info.sector_size;
- req->aiocb.aio_offset = sector * blk_info.sector_size;
- req->aiocb.data = req;
- req->next = NULL;
- return req;
-}
-
-static void blk_read_completed(struct blkfront_aiocb *aiocb, int ret)
-{
- struct blk_req *req = aiocb->data;
- if (ret)
- printk("got error code %d when reading at offset %ld\n", ret, aiocb->aio_offset);
- else
- blk_size_read += blk_info.sector_size;
- free(aiocb->aio_buf);
- free(req);
-}
-
-static void blk_read_sector(uint64_t sector)
-{
- struct blk_req *req;
-
- req = blk_alloc_req(sector);
- req->aiocb.aio_cb = blk_read_completed;
-
- blkfront_aio_read(&req->aiocb);
-}
-
-#ifdef BLKTEST_WRITE
-static void blk_write_read_completed(struct blkfront_aiocb *aiocb, int ret)
-{
- struct blk_req *req = aiocb->data;
- int rand_value;
- int i;
- int *buf;
-
- if (ret) {
- printk("got error code %d when reading back at offset %ld\n", ret, aiocb->aio_offset);
- free(aiocb->aio_buf);
- free(req);
- return;
- }
- blk_size_read += blk_info.sector_size;
- buf = (int*) aiocb->aio_buf;
- rand_value = req->rand_value;
- for (i = 0; i < blk_info.sector_size / sizeof(int); i++) {
- if (buf[i] != rand_value) {
- printk("bogus data at offset %ld\n", aiocb->aio_offset + i);
- break;
- }
- rand_value *= RAND_MIX;
- }
- free(aiocb->aio_buf);
- free(req);
-}
-
-static void blk_write_completed(struct blkfront_aiocb *aiocb, int ret)
-{
- struct blk_req *req = aiocb->data;
- if (ret) {
- printk("got error code %d when writing at offset %ld\n", ret, aiocb->aio_offset);
- free(aiocb->aio_buf);
- free(req);
- return;
- }
- blk_size_write += blk_info.sector_size;
- /* Push write check */
- req->next = blk_to_read;
- blk_to_read = req;
-}
-
-static void blk_write_sector(uint64_t sector)
-{
- struct blk_req *req;
- int rand_value;
- int i;
- int *buf;
-
- req = blk_alloc_req(sector);
- req->aiocb.aio_cb = blk_write_completed;
- req->rand_value = rand_value = rand();
-
- buf = (int*) req->aiocb.aio_buf;
- for (i = 0; i < blk_info.sector_size / sizeof(int); i++) {
- buf[i] = rand_value;
- rand_value *= RAND_MIX;
- }
-
- blkfront_aio_write(&req->aiocb);
-}
-#endif
-
-static void blkfront_thread(void *p)
-{
- time_t lasttime = 0;
-
- blk_dev = init_blkfront(NULL, &blk_info);
- if (!blk_dev) {
- up(&blk_sem);
- return;
- }
-
- if (blk_info.info & VDISK_CDROM)
- printk("Block device is a CDROM\n");
- if (blk_info.info & VDISK_REMOVABLE)
- printk("Block device is removable\n");
- if (blk_info.info & VDISK_READONLY)
- printk("Block device is read-only\n");
-
-#ifdef BLKTEST_WRITE
- if (blk_info.mode == O_RDWR) {
- blk_write_sector(0);
- blk_write_sector(blk_info.sectors-1);
- } else
-#endif
- {
- blk_read_sector(0);
- blk_read_sector(blk_info.sectors-1);
- }
-
- while (!do_shutdown) {
- uint64_t sector = rand() % blk_info.sectors;
- struct timeval tv;
-#ifdef BLKTEST_WRITE
- if (blk_info.mode == O_RDWR)
- blk_write_sector(sector);
- else
-#endif
- blk_read_sector(sector);
- blkfront_aio_poll(blk_dev);
- gettimeofday(&tv, NULL);
- if (tv.tv_sec > lasttime + 10) {
- printk("%llu read, %llu write\n", blk_size_read, blk_size_write);
- lasttime = tv.tv_sec;
- }
-
-#ifdef BLKTEST_WRITE
- while (blk_to_read) {
- struct blk_req *req = blk_to_read;
- blk_to_read = blk_to_read->next;
- req->aiocb.aio_cb = blk_write_read_completed;
- blkfront_aio_read(&req->aiocb);
- }
-#endif
- }
- up(&blk_sem);
-}
-#endif
-
-#if defined(CONFIG_FBFRONT) && defined(CONFIG_KBDFRONT)
-#define WIDTH 800
-#define HEIGHT 600
-#define DEPTH 32
-
-static uint32_t *fb;
-static int refresh_period = 50;
-static struct fbfront_dev *fb_dev;
-static struct semaphore fbfront_sem = __SEMAPHORE_INITIALIZER(fbfront_sem, 0);
-
-static void fbfront_drawvert(int x, int y1, int y2, uint32_t color)
-{
- int y;
- if (x < 0)
- return;
- if (x >= WIDTH)
- return;
- if (y1 < 0)
- y1 = 0;
- if (y2 >= HEIGHT)
- y2 = HEIGHT-1;
- for (y = y1; y <= y2; y++)
- fb[x + y*WIDTH] ^= color;
-}
-
-static void fbfront_drawhoriz(int x1, int x2, int y, uint32_t color)
-{
- int x;
- if (y < 0)
- return;
- if (y >= HEIGHT)
- return;
- if (x1 < 0)
- x1 = 0;
- if (x2 >= WIDTH)
- x2 = WIDTH-1;
- for (x = x1; x <= x2; x++)
- fb[x + y*WIDTH] ^= color;
-}
-
-static void fbfront_thread(void *p)
-{
- size_t line_length = WIDTH * (DEPTH / 8);
- size_t memsize = HEIGHT * line_length;
- unsigned long *mfns;
- int i, n = (memsize + PAGE_SIZE-1) / PAGE_SIZE;
-
- memsize = n * PAGE_SIZE;
- fb = _xmalloc(memsize, PAGE_SIZE);
- memset(fb, 0, memsize);
- mfns = xmalloc_array(unsigned long, n);
- for (i = 0; i < n; i++)
- mfns[i] = virtual_to_mfn((char *) fb + i * PAGE_SIZE);
- fb_dev = init_fbfront(NULL, mfns, WIDTH, HEIGHT, DEPTH, line_length, n);
- xfree(mfns);
- if (!fb_dev) {
- xfree(fb);
- }
- up(&fbfront_sem);
-}
-
-static void clip_cursor(int *x, int *y)
-{
- if (*x < 0)
- *x = 0;
- if (*x >= WIDTH)
- *x = WIDTH - 1;
- if (*y < 0)
- *y = 0;
- if (*y >= HEIGHT)
- *y = HEIGHT - 1;
-}
-
-static void refresh_cursor(int new_x, int new_y)
-{
- static int old_x = -1, old_y = -1;
-
- if (!refresh_period)
- return;
-
- if (old_x != -1 && old_y != -1) {
- fbfront_drawvert(old_x, old_y + 1, old_y + 8, 0xffffffff);
- fbfront_drawhoriz(old_x + 1, old_x + 8, old_y, 0xffffffff);
- fbfront_update(fb_dev, old_x, old_y, 9, 9);
- }
- old_x = new_x;
- old_y = new_y;
- fbfront_drawvert(new_x, new_y + 1, new_y + 8, 0xffffffff);
- fbfront_drawhoriz(new_x + 1, new_x + 8, new_y, 0xffffffff);
- fbfront_update(fb_dev, new_x, new_y, 9, 9);
-}
-
-static struct kbdfront_dev *kbd_dev;
-static struct semaphore kbd_sem = __SEMAPHORE_INITIALIZER(kbd_sem, 0);
-static void kbdfront_thread(void *p)
-{
- DEFINE_WAIT(w);
- DEFINE_WAIT(w2);
- DEFINE_WAIT(w3);
- int x = WIDTH / 2, y = HEIGHT / 2, z = 0;
-
- kbd_dev = init_kbdfront(NULL, 1);
- down(&fbfront_sem);
- if (!kbd_dev) {
- up(&kbd_sem);
- return;
- }
-
- refresh_cursor(x, y);
- while (1) {
- union xenkbd_in_event kbdevent;
- union xenfb_in_event fbevent;
- int sleep = 1;
-
- add_waiter(w, kbdfront_queue);
- add_waiter(w2, fbfront_queue);
- add_waiter(w3, shutdown_queue);
-
- rmb();
- if (do_shutdown)
- break;
-
- while (kbdfront_receive(kbd_dev, &kbdevent, 1) != 0) {
- sleep = 0;
- switch(kbdevent.type) {
- case XENKBD_TYPE_MOTION:
- printk("motion x:%d y:%d z:%d\n",
- kbdevent.motion.rel_x,
- kbdevent.motion.rel_y,
- kbdevent.motion.rel_z);
- x += kbdevent.motion.rel_x;
- y += kbdevent.motion.rel_y;
- z += kbdevent.motion.rel_z;
- clip_cursor(&x, &y);
- refresh_cursor(x, y);
- break;
- case XENKBD_TYPE_POS:
- printk("pos x:%d y:%d dz:%d\n",
- kbdevent.pos.abs_x,
- kbdevent.pos.abs_y,
- kbdevent.pos.rel_z);
- x = kbdevent.pos.abs_x;
- y = kbdevent.pos.abs_y;
- z = kbdevent.pos.rel_z;
- clip_cursor(&x, &y);
- refresh_cursor(x, y);
- break;
- case XENKBD_TYPE_KEY:
- printk("key %d %s\n",
- kbdevent.key.keycode,
- kbdevent.key.pressed ? "pressed" : "released");
- if (kbdevent.key.keycode == BTN_LEFT) {
- printk("mouse %s at (%d,%d,%d)\n",
- kbdevent.key.pressed ? "clic" : "release", x, y, z);
- if (kbdevent.key.pressed) {
- uint32_t color = rand();
- fbfront_drawvert(x - 16, y - 16, y + 15, color);
- fbfront_drawhoriz(x - 16, x + 15, y + 16, color);
- fbfront_drawvert(x + 16, y - 15, y + 16, color);
- fbfront_drawhoriz(x - 15, x + 16, y - 16, color);
- fbfront_update(fb_dev, x - 16, y - 16, 33, 33);
- }
- } else if (kbdevent.key.keycode == KEY_Q) {
- shutdown_reason = SHUTDOWN_poweroff;
- wmb();
- do_shutdown = 1;
- wmb();
- wake_up(&shutdown_queue);
- }
- break;
- }
- }
- while (fbfront_receive(fb_dev, &fbevent, 1) != 0) {
- sleep = 0;
- switch(fbevent.type) {
- case XENFB_TYPE_REFRESH_PERIOD:
- refresh_period = fbevent.refresh_period.period;
- printk("refresh period %d\n", refresh_period);
- refresh_cursor(x, y);
- break;
- }
- }
- if (sleep)
- schedule();
- remove_waiter(w3, shutdown_queue);
- remove_waiter(w2, fbfront_queue);
- remove_waiter(w, kbdfront_queue);
- }
- up(&kbd_sem);
-}
-#endif
-
-#ifdef CONFIG_PCIFRONT
-static struct pcifront_dev *pci_dev;
-static struct semaphore pci_sem = __SEMAPHORE_INITIALIZER(pci_sem, 0);
-
-static void print_pcidev(unsigned int domain, unsigned int bus, unsigned int slot, unsigned int fun)
-{
- unsigned int vendor, device, rev, class;
-
- pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x00, 2, &vendor);
- pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x02, 2, &device);
- pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x08, 1, &rev);
- pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x0a, 2, &class);
-
- printk("%04x:%02x:%02x.%02x %04x: %04x:%04x (rev %02x)\n", domain, bus, slot, fun, class, vendor, device, rev);
-}
-
-static void pcifront_thread(void *p)
-{
- pcifront_watches(NULL);
- pci_dev = init_pcifront(NULL);
- if (!pci_dev) {
- up(&pci_sem);
- return;
- }
- printk("PCI devices:\n");
- pcifront_scan(pci_dev, print_pcidev);
- up(&pci_sem);
-}
-#endif
-
-void shutdown_frontends(void)
-{
-#ifdef CONFIG_NETFRONT
- down(&net_sem);
- if (net_dev)
- shutdown_netfront(net_dev);
-#endif
-
-#ifdef CONFIG_BLKFRONT
- down(&blk_sem);
- if (blk_dev)
- shutdown_blkfront(blk_dev);
-#endif
-
-#if defined(CONFIG_FBFRONT) && defined(CONFIG_KBDFRONT)
- if (fb_dev)
- shutdown_fbfront(fb_dev);
-
- down(&kbd_sem);
- if (kbd_dev)
- shutdown_kbdfront(kbd_dev);
-#endif
-
-#ifdef CONFIG_PCIFRONT
- down(&pci_sem);
- if (pci_dev)
- shutdown_pcifront(pci_dev);
-#endif
-}
-
-#ifdef CONFIG_XENBUS
-void app_shutdown(unsigned reason)
-{
- shutdown_reason = reason;
- wmb();
- do_shutdown = 1;
- wmb();
- wake_up(&shutdown_queue);
-}
-
-static void shutdown_thread(void *p)
-{
- DEFINE_WAIT(w);
-
- while (1) {
- add_waiter(w, shutdown_queue);
- rmb();
- if (do_shutdown) {
- rmb();
- break;
- }
- schedule();
- remove_waiter(w, shutdown_queue);
- }
-
- shutdown_frontends();
-
- HYPERVISOR_shutdown(shutdown_reason);
-}
-#endif
-
-int app_main(start_info_t *si)
-{
- printk("Test main: start_info=%p\n", si);
-#ifdef CONFIG_XENBUS
- create_thread("xenbus_tester", xenbus_tester, si);
-#endif
- create_thread("periodic_thread", periodic_thread, si);
-#ifdef CONFIG_NETFRONT
- create_thread("netfront", netfront_thread, si);
-#endif
-#ifdef CONFIG_BLKFRONT
- create_thread("blkfront", blkfront_thread, si);
-#endif
-#if defined(CONFIG_FBFRONT) && defined(CONFIG_KBDFRONT)
- create_thread("fbfront", fbfront_thread, si);
- create_thread("kbdfront", kbdfront_thread, si);
-#endif
-#ifdef CONFIG_PCIFRONT
- create_thread("pcifront", pcifront_thread, si);
-#endif
-#ifdef CONFIG_XENBUS
- create_thread("shutdown", shutdown_thread, si);
-#endif
- return 0;
-}
+++ /dev/null
-/*
- * Copyright (c) 2010-2012 United States Government, as represented by
- * the Secretary of Defense. All rights reserved.
- *
- * This code has been derived from drivers/char/tpm.c
- * from the linux kernel
- *
- * Copyright (C) 2004 IBM Corporation
- *
- * This code has also been derived from drivers/char/tpm/tpm_tis.c
- * from the linux kernel
- *
- * Copyright (C) 2005, 2006 IBM Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, version 2
- * of the License
- */
-#include <mini-os/ioremap.h>
-#include <mini-os/iorw.h>
-#include <mini-os/tpm_tis.h>
-#include <mini-os/os.h>
-#include <mini-os/sched.h>
-#include <mini-os/byteorder.h>
-#include <mini-os/events.h>
-#include <mini-os/wait.h>
-#include <mini-os/xmalloc.h>
-#include <mini-os/lib.h>
-#include <errno.h>
-#include <stdbool.h>
-
-#ifndef min
- #define min( a, b ) ( ((a) < (b)) ? (a) : (b) )
-#endif
-#define ADJUST_TIMEOUTS_TO_STANDARD(initial,standard,timeout_no) \
- if((initial) < (standard)){ \
- (initial) = (standard); \
- printk("Timeout %c was adjusted to standard value.\n",timeout_no); \
- }
-
-#define TPM_HEADER_SIZE 10
-
-#define TPM_BUFSIZE 2048
-
-struct tpm_input_header {
- uint16_t tag;
- uint32_t length;
- uint32_t ordinal;
-}__attribute__((packed));
-
-struct tpm_output_header {
- uint16_t tag;
- uint32_t length;
- uint32_t return_code;
-}__attribute__((packed));
-
-struct stclear_flags_t {
- uint16_t tag;
- uint8_t deactivated;
- uint8_t disableForceClear;
- uint8_t physicalPresence;
- uint8_t physicalPresenceLock;
- uint8_t bGlobalLock;
-}__attribute__((packed));
-
-struct tpm_version_t {
- uint8_t Major;
- uint8_t Minor;
- uint8_t revMajor;
- uint8_t revMinor;
-}__attribute__((packed));
-
-struct tpm_version_1_2_t {
- uint16_t tag;
- uint8_t Major;
- uint8_t Minor;
- uint8_t revMajor;
- uint8_t revMinor;
-}__attribute__((packed));
-
-struct timeout_t {
- uint32_t a;
- uint32_t b;
- uint32_t c;
- uint32_t d;
-}__attribute__((packed));
-
-struct duration_t {
- uint32_t tpm_short;
- uint32_t tpm_medium;
- uint32_t tpm_long;
-}__attribute__((packed));
-
-struct permanent_flags_t {
- uint16_t tag;
- uint8_t disable;
- uint8_t ownership;
- uint8_t deactivated;
- uint8_t readPubek;
- uint8_t disableOwnerClear;
- uint8_t allowMaintenance;
- uint8_t physicalPresenceLifetimeLock;
- uint8_t physicalPresenceHWEnable;
- uint8_t physicalPresenceCMDEnable;
- uint8_t CEKPUsed;
- uint8_t TPMpost;
- uint8_t TPMpostLock;
- uint8_t FIPS;
- uint8_t operator;
- uint8_t enableRevokeEK;
- uint8_t nvLocked;
- uint8_t readSRKPub;
- uint8_t tpmEstablished;
- uint8_t maintenanceDone;
- uint8_t disableFullDALogicInfo;
-}__attribute__((packed));
-
-typedef union {
- struct permanent_flags_t perm_flags;
- struct stclear_flags_t stclear_flags;
- bool owned;
- uint32_t num_pcrs;
- struct tpm_version_t tpm_version;
- struct tpm_version_1_2_t tpm_version_1_2;
- uint32_t manufacturer_id;
- struct timeout_t timeout;
- struct duration_t duration;
-} cap_t;
-
-struct tpm_getcap_params_in {
- uint32_t cap;
- uint32_t subcap_size;
- uint32_t subcap;
-}__attribute__((packed));
-
-struct tpm_getcap_params_out {
- uint32_t cap_size;
- cap_t cap;
-}__attribute__((packed));
-
-struct tpm_readpubek_params_out {
- uint8_t algorithm[4];
- uint8_t encscheme[2];
- uint8_t sigscheme[2];
- uint32_t paramsize;
- uint8_t parameters[12]; /*assuming RSA*/
- uint32_t keysize;
- uint8_t modulus[256];
- uint8_t checksum[20];
-}__attribute__((packed));
-
-typedef union {
- struct tpm_input_header in;
- struct tpm_output_header out;
-} tpm_cmd_header;
-
-#define TPM_DIGEST_SIZE 20
-struct tpm_pcrread_out {
- uint8_t pcr_result[TPM_DIGEST_SIZE];
-}__attribute__((packed));
-
-struct tpm_pcrread_in {
- uint32_t pcr_idx;
-}__attribute__((packed));
-
-struct tpm_pcrextend_in {
- uint32_t pcr_idx;
- uint8_t hash[TPM_DIGEST_SIZE];
-}__attribute__((packed));
-
-typedef union {
- struct tpm_getcap_params_out getcap_out;
- struct tpm_readpubek_params_out readpubek_out;
- uint8_t readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)];
- struct tpm_getcap_params_in getcap_in;
- struct tpm_pcrread_in pcrread_in;
- struct tpm_pcrread_out pcrread_out;
- struct tpm_pcrextend_in pcrextend_in;
-} tpm_cmd_params;
-
-struct tpm_cmd_t {
- tpm_cmd_header header;
- tpm_cmd_params params;
-}__attribute__((packed));
-
-
-enum tpm_duration {
- TPM_SHORT = 0,
- TPM_MEDIUM = 1,
- TPM_LONG = 2,
- TPM_UNDEFINED,
-};
-
-#define TPM_MAX_ORDINAL 243
-#define TPM_MAX_PROTECTED_ORDINAL 12
-#define TPM_PROTECTED_ORDINAL_MASK 0xFF
-
-extern const uint8_t tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL];
-extern const uint8_t tpm_ordinal_duration[TPM_MAX_ORDINAL];
-
-#define TPM_DIGEST_SIZE 20
-#define TPM_ERROR_SIZE 10
-#define TPM_RET_CODE_IDX 6
-
-/* tpm_capabilities */
-#define TPM_CAP_FLAG cpu_to_be32(4)
-#define TPM_CAP_PROP cpu_to_be32(5)
-#define CAP_VERSION_1_1 cpu_to_be32(0x06)
-#define CAP_VERSION_1_2 cpu_to_be32(0x1A)
-
-/* tpm_sub_capabilities */
-#define TPM_CAP_PROP_PCR cpu_to_be32(0x101)
-#define TPM_CAP_PROP_MANUFACTURER cpu_to_be32(0x103)
-#define TPM_CAP_FLAG_PERM cpu_to_be32(0x108)
-#define TPM_CAP_FLAG_VOL cpu_to_be32(0x109)
-#define TPM_CAP_PROP_OWNER cpu_to_be32(0x111)
-#define TPM_CAP_PROP_TIS_TIMEOUT cpu_to_be32(0x115)
-#define TPM_CAP_PROP_TIS_DURATION cpu_to_be32(0x120)
-
-
-#define TPM_INTERNAL_RESULT_SIZE 200
-#define TPM_TAG_RQU_COMMAND cpu_to_be16(193)
-#define TPM_ORD_GET_CAP cpu_to_be32(101)
-
-extern const struct tpm_input_header tpm_getcap_header;
-
-
-
-const uint8_t tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
- TPM_UNDEFINED, /* 0 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 5 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 10 */
- TPM_SHORT,
-};
-
-const uint8_t tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
- TPM_UNDEFINED, /* 0 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 5 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 10 */
- TPM_SHORT,
- TPM_MEDIUM,
- TPM_LONG,
- TPM_LONG,
- TPM_MEDIUM, /* 15 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_MEDIUM,
- TPM_LONG,
- TPM_SHORT, /* 20 */
- TPM_SHORT,
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_SHORT, /* 25 */
- TPM_SHORT,
- TPM_MEDIUM,
- TPM_SHORT,
- TPM_SHORT,
- TPM_MEDIUM, /* 30 */
- TPM_LONG,
- TPM_MEDIUM,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT, /* 35 */
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_MEDIUM, /* 40 */
- TPM_LONG,
- TPM_MEDIUM,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT, /* 45 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_LONG,
- TPM_MEDIUM, /* 50 */
- TPM_MEDIUM,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 55 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_MEDIUM, /* 60 */
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_SHORT,
- TPM_SHORT,
- TPM_MEDIUM, /* 65 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 70 */
- TPM_SHORT,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 75 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_LONG, /* 80 */
- TPM_UNDEFINED,
- TPM_MEDIUM,
- TPM_LONG,
- TPM_SHORT,
- TPM_UNDEFINED, /* 85 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 90 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_UNDEFINED, /* 95 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_MEDIUM, /* 100 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 105 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 110 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT, /* 115 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_LONG, /* 120 */
- TPM_LONG,
- TPM_MEDIUM,
- TPM_UNDEFINED,
- TPM_SHORT,
- TPM_SHORT, /* 125 */
- TPM_SHORT,
- TPM_LONG,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT, /* 130 */
- TPM_MEDIUM,
- TPM_UNDEFINED,
- TPM_SHORT,
- TPM_MEDIUM,
- TPM_UNDEFINED, /* 135 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 140 */
- TPM_SHORT,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 145 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 150 */
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_SHORT,
- TPM_SHORT,
- TPM_UNDEFINED, /* 155 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 160 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 165 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_LONG, /* 170 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 175 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_MEDIUM, /* 180 */
- TPM_SHORT,
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_MEDIUM, /* 185 */
- TPM_SHORT,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 190 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 195 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 200 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT,
- TPM_SHORT, /* 205 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_MEDIUM, /* 210 */
- TPM_UNDEFINED,
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_UNDEFINED, /* 215 */
- TPM_MEDIUM,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT,
- TPM_SHORT, /* 220 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_UNDEFINED, /* 225 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 230 */
- TPM_LONG,
- TPM_MEDIUM,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 235 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 240 */
- TPM_UNDEFINED,
- TPM_MEDIUM,
-};
-
-const struct tpm_input_header tpm_getcap_header = {
- .tag = TPM_TAG_RQU_COMMAND,
- .length = cpu_to_be32(22),
- .ordinal = TPM_ORD_GET_CAP
-};
-
-
-enum tis_access {
- TPM_ACCESS_VALID = 0x80,
- TPM_ACCESS_ACTIVE_LOCALITY = 0x20, /* (R) */
- TPM_ACCESS_RELINQUISH_LOCALITY = 0x20,/* (W) */
- TPM_ACCESS_REQUEST_PENDING = 0x04, /* (W) */
- TPM_ACCESS_REQUEST_USE = 0x02, /* (W) */
-};
-
-enum tis_status {
- TPM_STS_VALID = 0x80, /* (R) */
- TPM_STS_COMMAND_READY = 0x40, /* (R) */
- TPM_STS_DATA_AVAIL = 0x10, /* (R) */
- TPM_STS_DATA_EXPECT = 0x08, /* (R) */
- TPM_STS_GO = 0x20, /* (W) */
-};
-
-enum tis_int_flags {
- TPM_GLOBAL_INT_ENABLE = 0x80000000,
- TPM_INTF_BURST_COUNT_STATIC = 0x100,
- TPM_INTF_CMD_READY_INT = 0x080,
- TPM_INTF_INT_EDGE_FALLING = 0x040,
- TPM_INTF_INT_EDGE_RISING = 0x020,
- TPM_INTF_INT_LEVEL_LOW = 0x010,
- TPM_INTF_INT_LEVEL_HIGH = 0x008,
- TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
- TPM_INTF_STS_VALID_INT = 0x002,
- TPM_INTF_DATA_AVAIL_INT = 0x001,
-};
-
-enum tis_defaults {
- TIS_MEM_BASE = 0xFED40000,
- TIS_MEM_LEN = 0x5000,
- TIS_SHORT_TIMEOUT = 750, /*ms*/
- TIS_LONG_TIMEOUT = 2000, /*2 sec */
-};
-
-#define TPM_TIMEOUT 5
-
-#define TPM_ACCESS(t, l) (((uint8_t*)t->pages[l]) + 0x0000)
-#define TPM_INT_ENABLE(t, l) ((uint32_t*)(((uint8_t*)t->pages[l]) + 0x0008))
-#define TPM_INT_VECTOR(t, l) (((uint8_t*)t->pages[l]) + 0x000C)
-#define TPM_INT_STATUS(t, l) (((uint8_t*)t->pages[l]) + 0x0010)
-#define TPM_INTF_CAPS(t, l) ((uint32_t*)(((uint8_t*)t->pages[l]) + 0x0014))
-#define TPM_STS(t, l) ((uint8_t*)(((uint8_t*)t->pages[l]) + 0x0018))
-#define TPM_DATA_FIFO(t, l) (((uint8_t*)t->pages[l]) + 0x0024)
-
-#define TPM_DID_VID(t, l) ((uint32_t*)(((uint8_t*)t->pages[l]) + 0x0F00))
-#define TPM_RID(t, l) (((uint8_t*)t->pages[l]) + 0x0F04)
-
-struct tpm_chip {
- int enabled_localities;
- int locality;
- unsigned long baseaddr;
- uint8_t* pages[5];
- int did, vid, rid;
-
- uint8_t data_buffer[TPM_BUFSIZE];
- int data_len;
-
- s_time_t timeout_a, timeout_b, timeout_c, timeout_d;
- s_time_t duration[3];
-
-#ifdef HAVE_LIBC
- int fd;
-#endif
-
- unsigned int irq;
- struct wait_queue_head read_queue;
- struct wait_queue_head int_queue;
-};
-
-
-static void __init_tpm_chip(struct tpm_chip* tpm) {
- tpm->enabled_localities = TPM_TIS_EN_LOCLALL;
- tpm->locality = -1;
- tpm->baseaddr = 0;
- tpm->pages[0] = tpm->pages[1] = tpm->pages[2] = tpm->pages[3] = tpm->pages[4] = NULL;
- tpm->vid = 0;
- tpm->did = 0;
- tpm->irq = 0;
- init_waitqueue_head(&tpm->read_queue);
- init_waitqueue_head(&tpm->int_queue);
-
- tpm->data_len = -1;
-
-#ifdef HAVE_LIBC
- tpm->fd = -1;
-#endif
-}
-
-/*
- * Returns max number of nsecs to wait
- */
-s_time_t tpm_calc_ordinal_duration(struct tpm_chip *chip,
- uint32_t ordinal)
-{
- int duration_idx = TPM_UNDEFINED;
- s_time_t duration = 0;
-
- if (ordinal < TPM_MAX_ORDINAL)
- duration_idx = tpm_ordinal_duration[ordinal];
- else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
- TPM_MAX_PROTECTED_ORDINAL)
- duration_idx =
- tpm_protected_ordinal_duration[ordinal &
- TPM_PROTECTED_ORDINAL_MASK];
-
- if (duration_idx != TPM_UNDEFINED) {
- duration = chip->duration[duration_idx];
- }
-
- if (duration <= 0) {
- return SECONDS(120);
- }
- else
- {
- return duration;
- }
-}
-
-
-static int locality_enabled(struct tpm_chip* tpm, int l) {
- return l >= 0 && tpm->enabled_localities & (1 << l);
-}
-
-static int check_locality(struct tpm_chip* tpm, int l) {
- if(locality_enabled(tpm, l) && (ioread8(TPM_ACCESS(tpm, l)) &
- (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
- (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
- return l;
- }
- return -1;
-}
-
-void release_locality(struct tpm_chip* tpm, int l, int force)
-{
- if (locality_enabled(tpm, l) && (force || (ioread8(TPM_ACCESS(tpm, l)) &
- (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
- (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))) {
- iowrite8(TPM_ACCESS(tpm, l), TPM_ACCESS_RELINQUISH_LOCALITY);
- }
-}
-
-int tpm_tis_request_locality(struct tpm_chip* tpm, int l) {
-
- s_time_t stop;
- /*Make sure locality is valid */
- if(!locality_enabled(tpm, l)) {
- printk("tpm_tis_change_locality() Tried to change to locality %d, but it is disabled or invalid!\n", l);
- return -1;
- }
- /* Check if we already have the current locality */
- if(check_locality(tpm, l) >= 0) {
- return tpm->locality = l;
- }
- /* Set the new locality*/
- iowrite8(TPM_ACCESS(tpm, l), TPM_ACCESS_REQUEST_USE);
-
- if(tpm->irq) {
- /* Wait for interrupt */
- wait_event_deadline(tpm->int_queue, (check_locality(tpm, l) >= 0), NOW() + tpm->timeout_a);
-
- /* FIXME: Handle timeout event, should return error in that case */
- return l;
- } else {
- /* Wait for burstcount */
- stop = NOW() + tpm->timeout_a;
- do {
- if(check_locality(tpm, l) >= 0) {
- return tpm->locality = l;
- }
- msleep(TPM_TIMEOUT);
- } while(NOW() < stop);
- }
-
- printk("REQ LOCALITY FAILURE\n");
- return -1;
-}
-
-static uint8_t tpm_tis_status(struct tpm_chip* tpm) {
- return ioread8(TPM_STS(tpm, tpm->locality));
-}
-
-/* This causes the current command to be aborted */
-static void tpm_tis_ready(struct tpm_chip* tpm) {
- iowrite8(TPM_STS(tpm, tpm->locality), TPM_STS_COMMAND_READY);
-}
-#define tpm_tis_cancel_cmd(v) tpm_tis_ready(v)
-
-static int get_burstcount(struct tpm_chip* tpm) {
- s_time_t stop;
- int burstcnt;
-
- stop = NOW() + tpm->timeout_d;
- do {
- burstcnt = ioread8((TPM_STS(tpm, tpm->locality) + 1));
- burstcnt += ioread8(TPM_STS(tpm, tpm->locality) + 2) << 8;
-
- if (burstcnt) {
- return burstcnt;
- }
- msleep(TPM_TIMEOUT);
- } while(NOW() < stop);
- return -EBUSY;
-}
-
-static int wait_for_stat(struct tpm_chip* tpm, uint8_t mask,
- unsigned long timeout, struct wait_queue_head* queue) {
- s_time_t stop;
- uint8_t status;
-
- status = tpm_tis_status(tpm);
- if((status & mask) == mask) {
- return 0;
- }
-
- if(tpm->irq) {
- wait_event_deadline(*queue, ((tpm_tis_status(tpm) & mask) == mask), timeout);
- /* FIXME: Check for timeout and return -ETIME */
- return 0;
- } else {
- stop = NOW() + timeout;
- do {
- msleep(TPM_TIMEOUT);
- status = tpm_tis_status(tpm);
- if((status & mask) == mask)
- return 0;
- } while( NOW() < stop);
- }
- return -ETIME;
-}
-
-static int recv_data(struct tpm_chip* tpm, uint8_t* buf, size_t count) {
- int size = 0;
- int burstcnt;
- while( size < count &&
- wait_for_stat(tpm,
- TPM_STS_DATA_AVAIL | TPM_STS_VALID,
- tpm->timeout_c,
- &tpm->read_queue)
- == 0) {
- burstcnt = get_burstcount(tpm);
- for(; burstcnt > 0 && size < count; --burstcnt)
- {
- buf[size++] = ioread8(TPM_DATA_FIFO(tpm, tpm->locality));
- }
- }
- return size;
-}
-
-int tpm_tis_recv(struct tpm_chip* tpm, uint8_t* buf, size_t count) {
- int size = 0;
- int expected, status;
-
- if (count < TPM_HEADER_SIZE) {
- size = -EIO;
- goto out;
- }
-
- /* read first 10 bytes, including tag, paramsize, and result */
- if((size =
- recv_data(tpm, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) {
- printk("Error reading tpm cmd header\n");
- goto out;
- }
-
- expected = be32_to_cpu(*((uint32_t*)(buf + 2)));
- if(expected > count) {
- size = -EIO;
- goto out;
- }
-
- if((size += recv_data(tpm, & buf[TPM_HEADER_SIZE],
- expected - TPM_HEADER_SIZE)) < expected) {
- printk("Unable to read rest of tpm command size=%d expected=%d\n", size, expected);
- size = -ETIME;
- goto out;
- }
-
- wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c, &tpm->int_queue);
- status = tpm_tis_status(tpm);
- if(status & TPM_STS_DATA_AVAIL) {
- printk("Error: left over data\n");
- size = -EIO;
- goto out;
- }
-
-out:
- tpm_tis_ready(tpm);
- release_locality(tpm, tpm->locality, 0);
- return size;
-}
-int tpm_tis_send(struct tpm_chip* tpm, uint8_t* buf, size_t len) {
- int rc;
- int status, burstcnt = 0;
- int count = 0;
- uint32_t ordinal;
-
- if(tpm_tis_request_locality(tpm, tpm->locality) < 0) {
- return -EBUSY;
- }
-
- status = tpm_tis_status(tpm);
- if((status & TPM_STS_COMMAND_READY) == 0) {
- tpm_tis_ready(tpm);
- if(wait_for_stat(tpm, TPM_STS_COMMAND_READY, tpm->timeout_b, &tpm->int_queue) < 0) {
- rc = -ETIME;
- goto out_err;
- }
- }
-
- while(count < len - 1) {
- burstcnt = get_burstcount(tpm);
- for(;burstcnt > 0 && count < len -1; --burstcnt) {
- iowrite8(TPM_DATA_FIFO(tpm, tpm->locality), buf[count++]);
- }
-
- wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c, &tpm->int_queue);
- status = tpm_tis_status(tpm);
- if((status & TPM_STS_DATA_EXPECT) == 0) {
- rc = -EIO;
- goto out_err;
- }
- }
-
- /*Write last byte*/
- iowrite8(TPM_DATA_FIFO(tpm, tpm->locality), buf[count]);
- wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c, &tpm->read_queue);
- status = tpm_tis_status(tpm);
- if((status & TPM_STS_DATA_EXPECT) != 0) {
- rc = -EIO;
- goto out_err;
- }
-
- /*go and do it*/
- iowrite8(TPM_STS(tpm, tpm->locality), TPM_STS_GO);
-
- if(tpm->irq) {
- /*Wait for interrupt */
- ordinal = be32_to_cpu(*(buf + 6));
- if(wait_for_stat(tpm,
- TPM_STS_DATA_AVAIL | TPM_STS_VALID,
- tpm_calc_ordinal_duration(tpm, ordinal),
- &tpm->read_queue) < 0) {
- rc = -ETIME;
- goto out_err;
- }
- }
-#ifdef HAVE_LIBC
- if(tpm->fd >= 0) {
- files[tpm->fd].read = 0;
- files[tpm->fd].tpm_tis.respgot = 0;
- files[tpm->fd].tpm_tis.offset = 0;
- }
-#endif
- return len;
-
-out_err:
- tpm_tis_ready(tpm);
- release_locality(tpm, tpm->locality, 0);
- return rc;
-}
-
-static void tpm_tis_irq_handler(evtchn_port_t port, struct pt_regs *regs, void* data)
-{
- struct tpm_chip* tpm = data;
- uint32_t interrupt;
- int i;
-
- interrupt = ioread32(TPM_INT_STATUS(tpm, tpm->locality));
- if(interrupt == 0) {
- return;
- }
-
- if(interrupt & TPM_INTF_DATA_AVAIL_INT) {
- wake_up(&tpm->read_queue);
- }
- if(interrupt & TPM_INTF_LOCALITY_CHANGE_INT) {
- for(i = 0; i < 5; ++i) {
- if(check_locality(tpm, i) >= 0) {
- break;
- }
- }
- }
- if(interrupt & (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
- TPM_INTF_CMD_READY_INT)) {
- wake_up(&tpm->int_queue);
- }
-
- /* Clear interrupts handled with TPM_EOI */
- iowrite32(TPM_INT_STATUS(tpm, tpm->locality), interrupt);
- ioread32(TPM_INT_STATUS(tpm, tpm->locality));
- return;
-}
-
-/*
- * Internal kernel interface to transmit TPM commands
- */
-static ssize_t tpm_transmit(struct tpm_chip *chip, const uint8_t *buf,
- size_t bufsiz)
-{
- ssize_t rc;
- uint32_t count, ordinal;
- s_time_t stop;
-
- count = be32_to_cpu(*((uint32_t *) (buf + 2)));
- ordinal = be32_to_cpu(*((uint32_t *) (buf + 6)));
- if (count == 0)
- return -ENODATA;
- if (count > bufsiz) {
- printk("Error: invalid count value %x %zx \n", count, bufsiz);
- return -E2BIG;
- }
-
- //down(&chip->tpm_mutex);
-
- if ((rc = tpm_tis_send(chip, (uint8_t *) buf, count)) < 0) {
- printk("tpm_transmit: tpm_send: error %ld\n", rc);
- goto out;
- }
-
- if (chip->irq)
- goto out_recv;
-
- stop = NOW() + tpm_calc_ordinal_duration(chip, ordinal);
- do {
- uint8_t status = tpm_tis_status(chip);
- if ((status & (TPM_STS_DATA_AVAIL | TPM_STS_VALID)) ==
- (TPM_STS_DATA_AVAIL | TPM_STS_VALID))
- goto out_recv;
-
- if ((status == TPM_STS_COMMAND_READY)) {
- printk("TPM Error: Operation Canceled\n");
- rc = -ECANCELED;
- goto out;
- }
-
- msleep(TPM_TIMEOUT); /* CHECK */
- rmb();
- } while (NOW() < stop);
-
- /* Cancel the command */
- tpm_tis_cancel_cmd(chip);
- printk("TPM Operation Timed out\n");
- rc = -ETIME;
- goto out;
-
-out_recv:
- if((rc = tpm_tis_recv(chip, (uint8_t *) buf, bufsiz)) < 0) {
- printk("tpm_transmit: tpm_recv: error %d\n", rc);
- }
-out:
- //up(&chip->tpm_mutex);
- return rc;
-}
-
-static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
- int len, const char *desc)
-{
- int err;
-
- len = tpm_transmit(chip,(uint8_t *) cmd, len);
- if (len < 0)
- return len;
- if (len == TPM_ERROR_SIZE) {
- err = be32_to_cpu(cmd->header.out.return_code);
- printk("A TPM error (%d) occurred %s\n", err, desc);
- return err;
- }
- return 0;
-}
-
-int tpm_get_timeouts(struct tpm_chip *chip)
-{
- struct tpm_cmd_t tpm_cmd;
- struct timeout_t *timeout_cap;
- struct duration_t *duration_cap;
- ssize_t rc;
- uint32_t timeout;
- unsigned int scale = 1;
-
- tpm_cmd.header.in = tpm_getcap_header;
- tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
- tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
- tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
-
- if((rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
- "attempting to determine the timeouts")) != 0) {
- printk("transmit failed %d\n", rc);
- goto duration;
- }
-
- if(be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
- be32_to_cpu(tpm_cmd.header.out.length) !=
- sizeof(tpm_cmd.header.out) + sizeof(uint32_t) + 4 * sizeof(uint32_t)) {
- return -EINVAL;
- }
-
- timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
- /* Don't overwrite default if value is 0 */
- timeout = be32_to_cpu(timeout_cap->a);
- if(timeout && timeout < 1000) {
- /* timeouts in msc rather usec */
- scale = 1000;
- }
- if (timeout)
- chip->timeout_a = MICROSECS(timeout * scale); /*Convert to msec */
- ADJUST_TIMEOUTS_TO_STANDARD(chip->timeout_a,MILLISECS(TIS_SHORT_TIMEOUT),'a');
-
- timeout = be32_to_cpu(timeout_cap->b);
- if (timeout)
- chip->timeout_b = MICROSECS(timeout * scale); /*Convert to msec */
- ADJUST_TIMEOUTS_TO_STANDARD(chip->timeout_b,MILLISECS(TIS_LONG_TIMEOUT),'b');
-
- timeout = be32_to_cpu(timeout_cap->c);
- if (timeout)
- chip->timeout_c = MICROSECS(timeout * scale); /*Convert to msec */
- ADJUST_TIMEOUTS_TO_STANDARD(chip->timeout_c,MILLISECS(TIS_SHORT_TIMEOUT),'c');
-
- timeout = be32_to_cpu(timeout_cap->d);
- if (timeout)
- chip->timeout_d = MICROSECS(timeout * scale); /*Convert to msec */
- ADJUST_TIMEOUTS_TO_STANDARD(chip->timeout_d,MILLISECS(TIS_SHORT_TIMEOUT),'d');
-
-duration:
- tpm_cmd.header.in = tpm_getcap_header;
- tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
- tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
- tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION;
-
- if((rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
- "attempting to determine the durations")) < 0) {
- return rc;
- }
-
- if(be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
- be32_to_cpu(tpm_cmd.header.out.length) !=
- sizeof(tpm_cmd.header.out) + sizeof(uint32_t) + 3 * sizeof(uint32_t)) {
- return -EINVAL;
- }
-
- duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
- chip->duration[TPM_SHORT] = MICROSECS(be32_to_cpu(duration_cap->tpm_short));
- chip->duration[TPM_MEDIUM] = MICROSECS(be32_to_cpu(duration_cap->tpm_medium));
- chip->duration[TPM_LONG] = MICROSECS(be32_to_cpu(duration_cap->tpm_long));
-
- /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
- * value wrong and apparently reports msecs rather than usecs. So we
- * fix up the resulting too-small TPM_SHORT value to make things work.
- */
- if (chip->duration[TPM_SHORT] < MILLISECS(10)) {
- chip->duration[TPM_SHORT] = SECONDS(1);
- chip->duration[TPM_MEDIUM] *= 1000;
- chip->duration[TPM_LONG] *= 1000;
- printk("Adjusting TPM timeout parameters\n");
- }
-
- return 0;
-}
-
-
-
-void tpm_continue_selftest(struct tpm_chip* chip) {
- uint8_t data[] = {
- 0, 193, /* TPM_TAG_RQU_COMMAND */
- 0, 0, 0, 10, /* length */
- 0, 0, 0, 83, /* TPM_ORD_GetCapability */
- };
-
- tpm_transmit(chip, data, sizeof(data));
-}
-
-ssize_t tpm_getcap(struct tpm_chip *chip, uint32_t subcap_id, cap_t *cap,
- const char *desc)
-{
- struct tpm_cmd_t tpm_cmd;
- int rc;
-
- tpm_cmd.header.in = tpm_getcap_header;
- if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) {
- tpm_cmd.params.getcap_in.cap = subcap_id;
- /*subcap field not necessary */
- tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(0);
- tpm_cmd.header.in.length -= cpu_to_be32(sizeof(uint32_t));
- } else {
- if (subcap_id == TPM_CAP_FLAG_PERM ||
- subcap_id == TPM_CAP_FLAG_VOL)
- tpm_cmd.params.getcap_in.cap = TPM_CAP_FLAG;
- else
- tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
- tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
- tpm_cmd.params.getcap_in.subcap = subcap_id;
- }
- rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc);
- if (!rc)
- *cap = tpm_cmd.params.getcap_out.cap;
- return rc;
-}
-
-
-struct tpm_chip* init_tpm_tis(unsigned long baseaddr, int localities, unsigned int irq)
-{
- int i;
- unsigned long addr;
- struct tpm_chip* tpm = NULL;
- uint32_t didvid;
- uint32_t intfcaps;
- uint32_t intmask;
-
- printk("============= Init TPM TIS Driver ==============\n");
-
- /*Sanity check the localities input */
- if(localities & ~TPM_TIS_EN_LOCLALL) {
- printk("init_tpm_tis() Invalid locality specification! %X\n", localities);
- goto abort_egress;
- }
-
- printk("IOMEM Machine Base Address: %lX\n", baseaddr);
-
- /* Create the tpm data structure */
- tpm = malloc(sizeof(struct tpm_chip));
- __init_tpm_chip(tpm);
-
- /* Set the enabled localities - if 0 we leave default as all enabled */
- if(localities != 0) {
- tpm->enabled_localities = localities;
- }
- printk("Enabled Localities: ");
- for(i = 0; i < 5; ++i) {
- if(locality_enabled(tpm, i)) {
- printk("%d ", i);
- }
- }
- printk("\n");
-
- /* Set the base machine address */
- tpm->baseaddr = baseaddr;
-
- /* Set default timeouts */
- tpm->timeout_a = MILLISECS(TIS_SHORT_TIMEOUT);
- tpm->timeout_b = MILLISECS(TIS_LONG_TIMEOUT);
- tpm->timeout_c = MILLISECS(TIS_SHORT_TIMEOUT);
- tpm->timeout_d = MILLISECS(TIS_SHORT_TIMEOUT);
-
- /*Map the mmio pages */
- addr = tpm->baseaddr;
- for(i = 0; i < 5; ++i) {
- if(locality_enabled(tpm, i)) {
- /* Map the page in now */
- if((tpm->pages[i] = ioremap_nocache(addr, PAGE_SIZE)) == NULL) {
- printk("Unable to map iomem page a address %p\n", addr);
- goto abort_egress;
- }
-
- /* Set default locality to the first enabled one */
- if (tpm->locality < 0) {
- if(tpm_tis_request_locality(tpm, i) < 0) {
- printk("Unable to request locality %d??\n", i);
- goto abort_egress;
- }
- }
- }
- addr += PAGE_SIZE;
- }
-
-
- /* Get the vendor and device ids */
- didvid = ioread32(TPM_DID_VID(tpm, tpm->locality));
- tpm->did = didvid >> 16;
- tpm->vid = didvid & 0xFFFF;
-
-
- /* Get the revision id */
- tpm->rid = ioread8(TPM_RID(tpm, tpm->locality));
-
- printk("1.2 TPM (device-id=0x%X vendor-id = %X rev-id = %X)\n", tpm->did, tpm->vid, tpm->rid);
-
- intfcaps = ioread32(TPM_INTF_CAPS(tpm, tpm->locality));
- printk("TPM interface capabilities (0x%x):\n", intfcaps);
- if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
- printk("\tBurst Count Static\n");
- if (intfcaps & TPM_INTF_CMD_READY_INT)
- printk("\tCommand Ready Int Support\n");
- if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
- printk("\tInterrupt Edge Falling\n");
- if (intfcaps & TPM_INTF_INT_EDGE_RISING)
- printk("\tInterrupt Edge Rising\n");
- if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
- printk("\tInterrupt Level Low\n");
- if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
- printk("\tInterrupt Level High\n");
- if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
- printk("\tLocality Change Int Support\n");
- if (intfcaps & TPM_INTF_STS_VALID_INT)
- printk("\tSts Valid Int Support\n");
- if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
- printk("\tData Avail Int Support\n");
-
- /*Interupt setup */
- intmask = ioread32(TPM_INT_ENABLE(tpm, tpm->locality));
-
- intmask |= TPM_INTF_CMD_READY_INT
- | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
- | TPM_INTF_STS_VALID_INT;
-
- iowrite32(TPM_INT_ENABLE(tpm, tpm->locality), intmask);
-
- /*If interupts are enabled, handle it */
- if(irq) {
- if(irq != TPM_PROBE_IRQ) {
- tpm->irq = irq;
- } else {
- /*FIXME add irq probing feature later */
- printk("IRQ probing not implemented\n");
- }
- }
-
- if(tpm->irq) {
- iowrite8(TPM_INT_VECTOR(tpm, tpm->locality), tpm->irq);
-
- if(bind_pirq(tpm->irq, 1, tpm_tis_irq_handler, tpm) != 0) {
- printk("Unabled to request irq: %u for use\n", tpm->irq);
- printk("Will use polling mode\n");
- tpm->irq = 0;
- } else {
- /* Clear all existing */
- iowrite32(TPM_INT_STATUS(tpm, tpm->locality), ioread32(TPM_INT_STATUS(tpm, tpm->locality)));
-
- /* Turn on interrupts */
- iowrite32(TPM_INT_ENABLE(tpm, tpm->locality), intmask | TPM_GLOBAL_INT_ENABLE);
- }
- }
-
- if(tpm_get_timeouts(tpm)) {
- printk("Could not get TPM timeouts and durations\n");
- goto abort_egress;
- }
- tpm_continue_selftest(tpm);
-
-
- return tpm;
-abort_egress:
- if(tpm != NULL) {
- shutdown_tpm_tis(tpm);
- }
- return NULL;
-}
-
-void shutdown_tpm_tis(struct tpm_chip* tpm){
- int i;
-
- printk("Shutting down tpm_tis device\n");
-
- iowrite32(TPM_INT_ENABLE(tpm, tpm->locality), ~TPM_GLOBAL_INT_ENABLE);
-
- /*Unmap all of the mmio pages */
- for(i = 0; i < 5; ++i) {
- if(tpm->pages[i] != NULL) {
- iounmap(tpm->pages[i], PAGE_SIZE);
- tpm->pages[i] = NULL;
- }
- }
- free(tpm);
- return;
-}
-
-
-int tpm_tis_cmd(struct tpm_chip* tpm, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen)
-{
- if(tpm->locality < 0) {
- printk("tpm_tis_cmd() failed! locality not set!\n");
- return -1;
- }
- if(reqlen > TPM_BUFSIZE) {
- reqlen = TPM_BUFSIZE;
- }
- memcpy(tpm->data_buffer, req, reqlen);
- *resplen = tpm_transmit(tpm, tpm->data_buffer, TPM_BUFSIZE);
-
- *resp = malloc(*resplen);
- memcpy(*resp, tpm->data_buffer, *resplen);
- return 0;
-}
-
-#ifdef HAVE_LIBC
-int tpm_tis_open(struct tpm_chip* tpm)
-{
- /* Silently prevent multiple opens */
- if(tpm->fd != -1) {
- return tpm->fd;
- }
-
- tpm->fd = alloc_fd(FTYPE_TPM_TIS);
- printk("tpm_tis_open() -> %d\n", tpm->fd);
- files[tpm->fd].tpm_tis.dev = tpm;
- files[tpm->fd].tpm_tis.offset = 0;
- files[tpm->fd].tpm_tis.respgot = 0;
- return tpm->fd;
-}
-
-int tpm_tis_posix_write(int fd, const uint8_t* buf, size_t count)
-{
- struct tpm_chip* tpm;
- tpm = files[fd].tpm_tis.dev;
-
- if(tpm->locality < 0) {
- printk("tpm_tis_posix_write() failed! locality not set!\n");
- errno = EINPROGRESS;
- return -1;
- }
- if(count == 0) {
- return 0;
- }
-
- /* Return an error if we are already processing a command */
- if(count > TPM_BUFSIZE) {
- count = TPM_BUFSIZE;
- }
- /* Send the command now */
- memcpy(tpm->data_buffer, buf, count);
- if((tpm->data_len = tpm_transmit(tpm, tpm->data_buffer, TPM_BUFSIZE)) < 0) {
- errno = EIO;
- return -1;
- }
- return count;
-}
-
-int tpm_tis_posix_read(int fd, uint8_t* buf, size_t count)
-{
- int rc;
- struct tpm_chip* tpm;
- tpm = files[fd].tpm_tis.dev;
-
- if(count == 0) {
- return 0;
- }
-
- /* If there is no tpm resp to read, return EIO */
- if(tpm->data_len < 0) {
- errno = EIO;
- return -1;
- }
-
-
- /* Handle EOF case */
- if(files[fd].tpm_tis.offset >= tpm->data_len) {
- rc = 0;
- } else {
- rc = min(tpm->data_len - files[fd].tpm_tis.offset, count);
- memcpy(buf, tpm->data_buffer + files[fd].tpm_tis.offset, rc);
- }
- files[fd].tpm_tis.offset += rc;
- /* Reset the data pending flag */
- return rc;
-}
-int tpm_tis_posix_fstat(int fd, struct stat* buf)
-{
- struct tpm_chip* tpm;
- tpm = files[fd].tpm_tis.dev;
-
- buf->st_mode = O_RDWR;
- buf->st_uid = 0;
- buf->st_gid = 0;
- buf->st_size = be32_to_cpu(*((uint32_t*)(tpm->data_buffer + 2)));
- buf->st_atime = buf->st_mtime = buf->st_ctime = time(NULL);
- return 0;
-}
-
-/* TPM 2.0 */
-
-/*TPM2.0 Selftest*/
-static void tpm2_selftest(struct tpm_chip* chip)
-{
- uint8_t data[] = {
- 0x80, 0x1,
- 0x0, 0x0, 0x0, 0xb,
- 0x0, 0x0, 0x1, 0x43,
- 0x1,
- };
-
- tpm_transmit(chip, data, sizeof(data));
-}
-
-struct tpm_chip* init_tpm2_tis(unsigned long baseaddr, int localities, unsigned int irq)
-{
- int i;
- unsigned long addr;
- struct tpm_chip* tpm = NULL;
- uint32_t didvid;
- uint32_t intfcaps;
- uint32_t intmask;
-
- printk("============= Init TPM2 TIS Driver ==============\n");
-
- /*Sanity check the localities input */
- if (localities & ~TPM_TIS_EN_LOCLALL) {
- printk("init_tpm2_tis Invalid locality specification! %X\n", localities);
- goto abort_egress;
- }
-
- printk("IOMEM Machine Base Address: %lX\n", baseaddr);
-
- /* Create the tpm data structure */
- tpm = malloc(sizeof(struct tpm_chip));
- __init_tpm_chip(tpm);
-
- /* Set the enabled localities - if 0 we leave default as all enabled */
- if (localities != 0) {
- tpm->enabled_localities = localities;
- }
- printk("Enabled Localities: ");
- for (i = 0; i < 5; ++i) {
- if (locality_enabled(tpm, i)) {
- printk("%d ", i);
- }
- }
- printk("\n");
-
- /* Set the base machine address */
- tpm->baseaddr = baseaddr;
-
- /* Set default timeouts */
- tpm->timeout_a = MILLISECS(TIS_SHORT_TIMEOUT);
- tpm->timeout_b = MILLISECS(TIS_LONG_TIMEOUT);
- tpm->timeout_c = MILLISECS(TIS_SHORT_TIMEOUT);
- tpm->timeout_d = MILLISECS(TIS_SHORT_TIMEOUT);
-
- /*Map the mmio pages */
- addr = tpm->baseaddr;
- for (i = 0; i < 5; ++i) {
- if (locality_enabled(tpm, i)) {
-
- /* Map the page in now */
- if ((tpm->pages[i] = ioremap_nocache(addr, PAGE_SIZE)) == NULL) {
- printk("Unable to map iomem page a address %p\n", addr);
- goto abort_egress;
- }
-
- /* Set default locality to the first enabled one */
- if (tpm->locality < 0) {
- if (tpm_tis_request_locality(tpm, i) < 0) {
- printk("Unable to request locality %d??\n", i);
- goto abort_egress;
- }
- }
- }
- addr += PAGE_SIZE;
- }
-
- /* Get the vendor and device ids */
- didvid = ioread32(TPM_DID_VID(tpm, tpm->locality));
- tpm->did = didvid >> 16;
- tpm->vid = didvid & 0xFFFF;
-
- /* Get the revision id */
- tpm->rid = ioread8(TPM_RID(tpm, tpm->locality));
- printk("2.0 TPM (device-id=0x%X vendor-id = %X rev-id = %X)\n",
- tpm->did, tpm->vid, tpm->rid);
-
- intfcaps = ioread32(TPM_INTF_CAPS(tpm, tpm->locality));
- printk("TPM interface capabilities (0x%x):\n", intfcaps);
- if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
- printk("\tBurst Count Static\n");
- if (intfcaps & TPM_INTF_CMD_READY_INT)
- printk("\tCommand Ready Int Support\n");
- if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
- printk("\tInterrupt Edge Falling\n");
- if (intfcaps & TPM_INTF_INT_EDGE_RISING)
- printk("\tInterrupt Edge Rising\n");
- if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
- printk("\tInterrupt Level Low\n");
- if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
- printk("\tInterrupt Level High\n");
- if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
- printk("\tLocality Change Int Support\n");
- if (intfcaps & TPM_INTF_STS_VALID_INT)
- printk("\tSts Valid Int Support\n");
- if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
- printk("\tData Avail Int Support\n");
-
- /*Interupt setup */
- intmask = ioread32(TPM_INT_ENABLE(tpm, tpm->locality));
-
- intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
- TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
-
- iowrite32(TPM_INT_ENABLE(tpm, tpm->locality), intmask);
-
- /*If interupts are enabled, handle it */
- if (irq) {
- if (irq != TPM_PROBE_IRQ) {
- tpm->irq = irq;
- } else {
- /*FIXME add irq probing feature later */
- printk("IRQ probing not implemented\n");
- }
- }
-
- if (tpm->irq) {
- iowrite8(TPM_INT_VECTOR(tpm, tpm->locality), tpm->irq);
- if (bind_pirq(tpm->irq, 1, tpm_tis_irq_handler, tpm) != 0) {
- printk("Unabled to request irq: %u for use\n", tpm->irq);
- printk("Will use polling mode\n");
- tpm->irq = 0;
- } else {
-
- /* Clear all existing */
- iowrite32(TPM_INT_STATUS(tpm, tpm->locality),
- ioread32(TPM_INT_STATUS(tpm, tpm->locality)));
-
- /* Turn on interrupts */
- iowrite32(TPM_INT_ENABLE(tpm, tpm->locality),
- intmask | TPM_GLOBAL_INT_ENABLE);
- }
- }
-
- tpm2_selftest(tpm);
- return tpm;
-
-abort_egress:
- if (tpm != NULL) {
- shutdown_tpm_tis(tpm);
- }
- return NULL;
-}
-#endif
+++ /dev/null
-/*
- * Copyright (c) 2010-2012 United States Government, as represented by
- * the Secretary of Defense. All rights reserved.
- *
- * This code has been derived from drivers/xen/tpmback/tpmback.c
- * from the xen 2.6.18 linux kernel
- *
- * Copyright (c) 2005, IBM Corporation
- *
- * which was itself derived from drivers/xen/netback/netback.c
- * from the xen 2.6.18 linux kernel
- *
- * Copyright (c) 2002-2004, K A Fraser
- *
- * This code has also been derived from drivers/xen/tpmback/xenbus.c
- * from the xen 2.6.18 linux kernel
- *
- * Copyright (C) 2005 IBM Corporation
- * Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
- *
- * This code has also been derived from drivers/xen/tpmback/interface.c
- * from the xen 2.6.18 linux kernel
- *
- * Copyright (c) 2005, IBM Corporation
- *
- * which was itself also derived from drvivers/xen/netback/interface.c
- * from the xen 2.6.18 linux kernel
- *
- * Copyright (c) 2004, Keir Fraser
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, version 2
- * of the License
- */
-#include <mini-os/os.h>
-#include <mini-os/xenbus.h>
-#include <mini-os/events.h>
-#include <errno.h>
-#include <mini-os/gnttab.h>
-#include <xen/io/xenbus.h>
-#include <xen/io/tpmif.h>
-#include <xen/io/protocols.h>
-#include <mini-os/xmalloc.h>
-#include <time.h>
-#include <mini-os/tpmback.h>
-#include <mini-os/lib.h>
-#include <fcntl.h>
-#include <mini-os/mm.h>
-#include <mini-os/posix/sys/mman.h>
-#include <mini-os/semaphore.h>
-#include <mini-os/wait.h>
-
-
-#ifndef HAVE_LIBC
-#define strtoul simple_strtoul
-#endif
-
-//#define TPMBACK_PRINT_DEBUG
-#ifdef TPMBACK_PRINT_DEBUG
-#define TPMBACK_DEBUG(fmt,...) printk("Tpmback:Debug("__FILE__":%d) " fmt, __LINE__, ##__VA_ARGS__)
-#define TPMBACK_DEBUG_MORE(fmt,...) printk(fmt, ##__VA_ARGS__)
-#else
-#define TPMBACK_DEBUG(fmt,...)
-#endif
-#define TPMBACK_ERR(fmt,...) printk("Tpmback:Error " fmt, ##__VA_ARGS__)
-#define TPMBACK_LOG(fmt,...) printk("Tpmback:Info " fmt, ##__VA_ARGS__)
-
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-
-/* Default size of the tpmif array at initialization */
-#define DEF_ARRAY_SIZE 1
-
-/* tpmif and tpmdev flags */
-#define TPMIF_CLOSED 1
-#define TPMIF_REQ_READY 2
-
-struct tpmif {
- domid_t domid;
- unsigned int handle;
-
- char* fe_path;
- char* fe_state_path;
-
- /* Locally bound event channel*/
- evtchn_port_t evtchn;
-
- /* Shared page */
- tpmif_shared_page_t *page;
-
- enum xenbus_state state;
- enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
-
- unsigned char uuid[16];
- void* opaque;
-
- /* state flags */
- int flags;
-};
-typedef struct tpmif tpmif_t;
-
-struct tpmback_dev {
-
- tpmif_t** tpmlist;
- unsigned long num_tpms;
- unsigned long num_alloc;
-
- struct gntmap map;
-
- /* True if at least one tpmif has a request to be handled */
- int flags;
-
- xenbus_event_queue events;
-
- /* Callbacks */
- void (*open_callback)(domid_t, unsigned int);
- void (*close_callback)(domid_t, unsigned int);
-};
-typedef struct tpmback_dev tpmback_dev_t;
-
-enum { EV_NONE, EV_NEWFE, EV_STCHNG } tpm_ev_enum;
-
-/* Global objects */
-static struct thread* eventthread = NULL;
-static tpmback_dev_t gtpmdev = {
- .tpmlist = NULL,
- .num_tpms = 0,
- .num_alloc = 0,
- .flags = TPMIF_CLOSED,
- .events = NULL,
- .open_callback = NULL,
- .close_callback = NULL,
-};
-struct wait_queue_head waitq;
-int globalinit = 0;
-
-/************************************
- * TPMIF SORTED ARRAY FUNCTIONS
- * tpmback_dev_t.tpmlist is a sorted array, sorted by domid and then handle number
- * Duplicates are not allowed
- * **********************************/
-
-static void tpmif_req_ready(tpmif_t* tpmif) {
- tpmif->flags |= TPMIF_REQ_READY;
- gtpmdev.flags |= TPMIF_REQ_READY;
-}
-
-static void tpmdev_check_req(void) {
- int i;
- int flags;
- local_irq_save(flags);
- for(i = 0; i < gtpmdev.num_tpms; ++i) {
- if(gtpmdev.tpmlist[i]->flags & TPMIF_REQ_READY) {
- gtpmdev.flags |= TPMIF_REQ_READY;
- local_irq_restore(flags);
- return;
- }
- }
- gtpmdev.flags &= ~TPMIF_REQ_READY;
- local_irq_restore(flags);
-}
-
-static void tpmif_req_finished(tpmif_t* tpmif) {
- tpmif->flags &= ~TPMIF_REQ_READY;
- tpmdev_check_req();
-}
-
-int __get_tpmif_index(int st, int n, domid_t domid, unsigned int handle)
-{
- int i = st + n /2;
- tpmif_t* tmp;
-
- if( n <= 0 )
- return -1;
-
- tmp = gtpmdev.tpmlist[i];
- if(domid == tmp->domid && tmp->handle == handle) {
- return i;
- } else if ( (domid < tmp->domid) ||
- (domid == tmp->domid && handle < tmp->handle)) {
- return __get_tpmif_index(st, n/2, domid, handle);
- } else {
- return __get_tpmif_index(i + 1, n/2 - ((n +1) % 2), domid, handle);
- }
-}
-
-/* Returns the array index of the tpmif domid/handle. Returns -1 if no such tpmif exists */
-int get_tpmif_index(domid_t domid, unsigned int handle)
-{
- int flags;
- int index;
- local_irq_save(flags);
- index = __get_tpmif_index(0, gtpmdev.num_tpms, domid, handle);
- local_irq_restore(flags);
- return index;
-}
-
-/* Returns the tpmif domid/handle or NULL if none exists */
-tpmif_t* get_tpmif(domid_t domid, unsigned int handle)
-{
- int flags;
- int i;
- tpmif_t* ret;
- local_irq_save(flags);
- i = get_tpmif_index(domid, handle);
- if (i < 0) {
- ret = NULL;
- } else {
- ret = gtpmdev.tpmlist[i];
- }
- local_irq_restore(flags);
- return ret;
-}
-
-/* Remove the given tpmif. Returns 0 if it was removed, -1 if it was not removed */
-int remove_tpmif(tpmif_t* tpmif)
-{
- int i, j;
- char* err;
- int flags;
- local_irq_save(flags);
-
- /* Find the index in the array if it exists */
- i = get_tpmif_index(tpmif->domid, tpmif->handle);
- if (i < 0) {
- goto error;
- }
-
- /* Remove the interface from the list */
- for(j = i; j < gtpmdev.num_tpms - 1; ++j) {
- gtpmdev.tpmlist[j] = gtpmdev.tpmlist[j+1];
- }
- gtpmdev.tpmlist[j] = NULL;
- --gtpmdev.num_tpms;
-
- /* If removed tpm was the only ready tpm, then we need to check and turn off the ready flag */
- tpmdev_check_req();
-
- local_irq_restore(flags);
-
- /* Stop listening for events on this tpm interface */
- if((err = xenbus_unwatch_path_token(XBT_NIL, tpmif->fe_state_path, tpmif->fe_state_path))) {
- TPMBACK_ERR("Unable to unwatch path token `%s' Error was %s Ignoring..\n", tpmif->fe_state_path, err);
- free(err);
- }
-
- return 0;
-error:
- local_irq_restore(flags);
- return -1;
-}
-
-/* Insert tpmif into dev->tpmlist. Returns 0 on success and non zero on error.
- * It is an error to insert a tpmif with the same domid and handle
- * number
- * as something already in the list */
-int insert_tpmif(tpmif_t* tpmif)
-{
- int flags;
- unsigned int i, j;
- tpmif_t* tmp;
- char* err;
- char path[512];
-
- local_irq_save(flags);
-
- /*Check if we need to allocate more space */
- if (gtpmdev.num_tpms == gtpmdev.num_alloc) {
- gtpmdev.num_alloc *= 2;
- gtpmdev.tpmlist = realloc(gtpmdev.tpmlist, gtpmdev.num_alloc);
- }
-
- /*Find where to put the new interface */
- for(i = 0; i < gtpmdev.num_tpms; ++i)
- {
- tmp = gtpmdev.tpmlist[i];
- if(tpmif->domid == tmp->domid && tpmif->handle == tmp->handle) {
- TPMBACK_ERR("Tried to insert duplicate tpm interface %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
- goto error;
- }
- if((tpmif->domid < tmp->domid) ||
- (tpmif->domid == tmp->domid && tpmif->handle < tmp->handle)) {
- break;
- }
- }
-
- /*Shift all the tpm pointers past i down one */
- for(j = gtpmdev.num_tpms; j > i; --j) {
- gtpmdev.tpmlist[j] = gtpmdev.tpmlist[j-1];
- }
-
- /*Add the new interface */
- gtpmdev.tpmlist[i] = tpmif;
- ++gtpmdev.num_tpms;
-
- /*Should not be needed, anything inserted with ready flag is probably an error */
- tpmdev_check_req();
-
- local_irq_restore(flags);
-
- snprintf(path, 512, "backend/vtpm/%u/%u/feature-protocol-v2", (unsigned int) tpmif->domid, tpmif->handle);
- if ((err = xenbus_write(XBT_NIL, path, "1")))
- {
- /* if we got an error here we should carefully remove the interface and then return */
- TPMBACK_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
- free(err);
- remove_tpmif(tpmif);
- goto error_post_irq;
- }
-
- /*Listen for state changes on the new interface */
- if((err = xenbus_watch_path_token(XBT_NIL, tpmif->fe_state_path, tpmif->fe_state_path, >pmdev.events)))
- {
- /* if we got an error here we should carefully remove the interface and then return */
- TPMBACK_ERR("Unable to watch path token `%s' Error was %s\n", tpmif->fe_state_path, err);
- free(err);
- remove_tpmif(tpmif);
- goto error_post_irq;
- }
- return 0;
-error:
- local_irq_restore(flags);
-error_post_irq:
- return -1;
-}
-
-
-/*****************
- * CHANGE BACKEND STATE
- * *****************/
-/*Attempts to change the backend state in xenstore
- * returns 0 on success and non-zero on error */
-int tpmif_change_state(tpmif_t* tpmif, enum xenbus_state state)
-{
- int tempst;
- char path[512];
- char *value;
- char *err;
- enum xenbus_state readst;
- TPMBACK_DEBUG("Backend state change %u/%u from=%d to=%d\n", (unsigned int) tpmif->domid, tpmif->handle, tpmif->state, state);
- if (tpmif->state == state)
- return 0;
-
- snprintf(path, 512, "backend/vtpm/%u/%u/state", (unsigned int) tpmif->domid, tpmif->handle);
-
- if((err = xenbus_read(XBT_NIL, path, &value))) {
- TPMBACK_ERR("Unable to read backend state %s, error was %s\n", path, err);
- free(err);
- return -1;
- }
- if(sscanf(value, "%d", &tempst) != 1) {
- TPMBACK_ERR("Non integer value (%s) in %s ??\n", value, path);
- free(value);
- return -1;
- }
- readst = (enum xenbus_state) tempst;
- free(value);
-
- /* It's possible that the backend state got updated by hotplug or something else behind our back */
- if(readst != tpmif->state) {
- TPMBACK_DEBUG("tpm interface state was %d but xenstore state was %d!\n", tpmif->state, readst);
- tpmif->state = readst;
- }
-
- /*If if the state isnt changing, then we dont update xenstore b/c we dont want to fire extraneous events */
- if(tpmif->state == state) {
- return 0;
- }
-
- /*update xenstore*/
- snprintf(path, 512, "backend/vtpm/%u/%u", (unsigned int) tpmif->domid, tpmif->handle);
- if((err = xenbus_printf(XBT_NIL, path, "state", "%u", state))) {
- TPMBACK_ERR("Error writing to xenstore %s, error was %s new state=%d\n", path, err, state);
- free(err);
- return -1;
- }
-
- tpmif->state = state;
-
- return 0;
-}
-/**********************************
- * TPMIF CREATION AND DELETION
- * *******************************/
-static tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
-{
- tpmif_t* tpmif;
- tpmif = malloc(sizeof(*tpmif));
- tpmif->domid = domid;
- tpmif->handle = handle;
- tpmif->fe_path = NULL;
- tpmif->fe_state_path = NULL;
- tpmif->state = XenbusStateInitialising;
- tpmif->status = DISCONNECTED;
- tpmif->page = NULL;
- tpmif->flags = 0;
- tpmif->opaque = NULL;
- memset(tpmif->uuid, 0, sizeof(tpmif->uuid));
- return tpmif;
-}
-
-void __free_tpmif(tpmif_t* tpmif)
-{
- if(tpmif->fe_path) {
- free(tpmif->fe_path);
- }
- if(tpmif->fe_state_path) {
- free(tpmif->fe_state_path);
- }
- free(tpmif);
-}
-/* Creates a new tpm interface, adds it to the sorted array and returns it.
- * returns NULL on error
- * If the tpm interface already exists, it is returned*/
-tpmif_t* new_tpmif(domid_t domid, unsigned int handle)
-{
- tpmif_t* tpmif;
- char* err;
- char path[512];
-
- /* Make sure we haven't already created this tpm
- * Double events can occur */
- if((tpmif = get_tpmif(domid, handle)) != NULL) {
- return tpmif;
- }
-
- tpmif = __init_tpmif(domid, handle);
-
- /* Get the uuid from xenstore */
- snprintf(path, 512, "backend/vtpm/%u/%u/uuid", (unsigned int) domid, handle);
- if((!xenbus_read_uuid(path, tpmif->uuid))) {
- TPMBACK_ERR("Error reading %s\n", path);
- goto error;
- }
-
- if(tpmif_change_state(tpmif, XenbusStateInitWait)) {
- goto error;
- }
-
- snprintf(path, 512, "backend/vtpm/%u/%u/frontend", (unsigned int) domid, handle);
- if((err = xenbus_read(XBT_NIL, path, &tpmif->fe_path))) {
- TPMBACK_ERR("Error creating new tpm instance xenbus_read(%s), Error = %s", path, err);
- free(err);
- goto error;
- }
-
- /*Set the state path */
- tpmif->fe_state_path = malloc(strlen(tpmif->fe_path) + 7);
- strcpy(tpmif->fe_state_path, tpmif->fe_path);
- strcat(tpmif->fe_state_path, "/state");
-
- if(insert_tpmif(tpmif)) {
- goto error;
- }
- TPMBACK_DEBUG("New tpmif %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
- /* Do the callback now */
- if(gtpmdev.open_callback) {
- gtpmdev.open_callback(tpmif->domid, tpmif->handle);
- }
- return tpmif;
-error:
- __free_tpmif(tpmif);
- return NULL;
-
-}
-
-/* Removes tpmif from dev->tpmlist and frees it's memory usage */
-void free_tpmif(tpmif_t* tpmif)
-{
- char* err;
- char path[512];
- TPMBACK_DEBUG("Free tpmif %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
- if(tpmif->flags & TPMIF_CLOSED) {
- TPMBACK_ERR("Tried to free an instance twice! Theres a bug somewhere!\n");
- BUG();
- }
- tpmif->flags = TPMIF_CLOSED;
-
- tpmif_change_state(tpmif, XenbusStateClosing);
-
- /* Unmap share page and unbind event channel */
- if(tpmif->status == CONNECTED) {
- tpmif->status = DISCONNECTING;
- mask_evtchn(tpmif->evtchn);
-
- if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
- TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
- }
-
- unbind_evtchn(tpmif->evtchn);
- }
- tpmif->status = DISCONNECTED;
- tpmif_change_state(tpmif, XenbusStateClosed);
-
- /* Do the callback now */
- if(gtpmdev.close_callback) {
- gtpmdev.close_callback(tpmif->domid, tpmif->handle);
- }
-
- /* remove from array */
- remove_tpmif(tpmif);
-
- /* Wake up anyone possibly waiting on this interface and let them exit */
- wake_up(&waitq);
- schedule();
-
- /* Remove the old xenbus entries */
- snprintf(path, 512, "backend/vtpm/%u/%u", (unsigned int) tpmif->domid, tpmif->handle);
- if((err = xenbus_rm(XBT_NIL, path))) {
- TPMBACK_ERR("Error cleaning up xenbus entries path=%s error=%s\n", path, err);
- free(err);
- }
-
- TPMBACK_LOG("Frontend %u/%u disconnected\n", (unsigned int) tpmif->domid, tpmif->handle);
-
- /* free memory */
- __free_tpmif(tpmif);
-
-}
-
-/**********************
- * REMAINING TPMBACK FUNCTIONS
- * ********************/
-
-/*Event channel handler */
-void tpmback_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
-{
- tpmif_t* tpmif = (tpmif_t*) data;
- tpmif_shared_page_t *pg = tpmif->page;
-
- switch (pg->state)
- {
- case TPMIF_STATE_SUBMIT:
- TPMBACK_DEBUG("EVENT CHANNEL FIRE %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
- tpmif_req_ready(tpmif);
- wake_up(&waitq);
- break;
- case TPMIF_STATE_CANCEL:
- /* If we are busy with a request, do nothing */
- if (tpmif->flags & TPMIF_REQ_READY)
- return;
- /* Acknowledge the cancellation if we are idle */
- pg->state = TPMIF_STATE_IDLE;
- wmb();
- notify_remote_via_evtchn(tpmif->evtchn);
- return;
- default:
- /* Spurious wakeup; do nothing */
- return;
- }
-}
-
-/* Connect to frontend */
-int connect_fe(tpmif_t* tpmif)
-{
- char path[512];
- char* err, *value;
- uint32_t domid;
- grant_ref_t ringref;
- evtchn_port_t evtchn;
-
- /* If already connected then quit */
- if (tpmif->status == CONNECTED) {
- TPMBACK_DEBUG("%u/%u tried to connect while it was already connected?\n", (unsigned int) tpmif->domid, tpmif->handle);
- return 0;
- }
-
- /* Fetch the grant reference */
- snprintf(path, 512, "%s/ring-ref", tpmif->fe_path);
- if((err = xenbus_read(XBT_NIL, path, &value))) {
- TPMBACK_ERR("Error creating new tpm instance xenbus_read(%s) Error = %s", path, err);
- free(err);
- return -1;
- }
- if(sscanf(value, "%d", &ringref) != 1) {
- TPMBACK_ERR("Non integer value (%s) in %s ??\n", value, path);
- free(value);
- return -1;
- }
- free(value);
-
-
- /* Fetch the event channel*/
- snprintf(path, 512, "%s/event-channel", tpmif->fe_path);
- if((err = xenbus_read(XBT_NIL, path, &value))) {
- TPMBACK_ERR("Error creating new tpm instance xenbus_read(%s) Error = %s", path, err);
- free(err);
- return -1;
- }
- if(sscanf(value, "%d", &evtchn) != 1) {
- TPMBACK_ERR("Non integer value (%s) in %s ??\n", value, path);
- free(value);
- return -1;
- }
- free(value);
-
- /* Check that protocol v2 is being used */
- snprintf(path, 512, "%s/feature-protocol-v2", tpmif->fe_path);
- if((err = xenbus_read(XBT_NIL, path, &value))) {
- TPMBACK_ERR("Unable to read %s during tpmback initialization! error = %s\n", path, err);
- free(err);
- return -1;
- }
- if(strcmp(value, "1")) {
- TPMBACK_ERR("%s has an invalid value (%s)\n", path, value);
- free(value);
- return -1;
- }
- free(value);
-
- domid = tpmif->domid;
- if((tpmif->page = gntmap_map_grant_refs(>pmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
- TPMBACK_ERR("Failed to map grant reference %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
- return -1;
- }
-
- /*Bind the event channel */
- if((evtchn_bind_interdomain(tpmif->domid, evtchn, tpmback_handler, tpmif, &tpmif->evtchn)))
- {
- TPMBACK_ERR("%u/%u Unable to bind to interdomain event channel!\n", (unsigned int) tpmif->domid, tpmif->handle);
- goto error_post_map;
- }
- unmask_evtchn(tpmif->evtchn);
-
- /* Write the ready flag and change status to connected */
- snprintf(path, 512, "backend/vtpm/%u/%u", (unsigned int) tpmif->domid, tpmif->handle);
- if((err = xenbus_printf(XBT_NIL, path, "ready", "%u", 1))) {
- TPMBACK_ERR("%u/%u Unable to write ready flag on connect_fe()\n", (unsigned int) tpmif->domid, tpmif->handle);
- free(err);
- goto error_post_evtchn;
- }
- tpmif->status = CONNECTED;
- if((tpmif_change_state(tpmif, XenbusStateConnected))){
- goto error_post_evtchn;
- }
-
- TPMBACK_LOG("Frontend %u/%u connected\n", (unsigned int) tpmif->domid, tpmif->handle);
-
- return 0;
-error_post_evtchn:
- mask_evtchn(tpmif->evtchn);
- unbind_evtchn(tpmif->evtchn);
-error_post_map:
- gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1);
- return -1;
-}
-
-static void disconnect_fe(tpmif_t* tpmif)
-{
- if (tpmif->status == CONNECTED) {
- tpmif->status = DISCONNECTING;
- mask_evtchn(tpmif->evtchn);
-
- if(gntmap_munmap(>pmdev.map, (unsigned long)tpmif->page, 1)) {
- TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
- }
-
- unbind_evtchn(tpmif->evtchn);
- }
- tpmif->status = DISCONNECTED;
- tpmif_change_state(tpmif, XenbusStateInitWait);
-
- TPMBACK_LOG("Frontend %u/%u disconnected\n", (unsigned int) tpmif->domid, tpmif->handle);
-}
-
-static int frontend_changed(tpmif_t* tpmif)
-{
- int state = xenbus_read_integer(tpmif->fe_state_path);
- if(state < 0) {
- state = XenbusStateUnknown;
- }
-
- TPMBACK_DEBUG("Frontend %u/%u state changed to %d\n", (unsigned int) tpmif->domid, tpmif->handle, state);
-
- switch (state) {
- case XenbusStateInitialising:
- break;
-
- case XenbusStateInitialised:
- case XenbusStateConnected:
- if(connect_fe(tpmif)) {
- TPMBACK_ERR("Failed to connect to front end %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
- tpmif_change_state(tpmif, XenbusStateClosed);
- return -1;
- }
- break;
-
- case XenbusStateClosing:
- tpmif_change_state(tpmif, XenbusStateClosing);
- break;
-
- case XenbusStateClosed:
- disconnect_fe(tpmif);
- break;
-
- case XenbusStateUnknown: /* keep it here */
- free_tpmif(tpmif);
- break;
-
- default:
- TPMBACK_DEBUG("BAD STATE CHANGE %u/%u state = %d for tpmif\n", (unsigned int) tpmif->domid, tpmif->handle, state);
- return -1;
- }
- return 0;
-}
-
-
-/* parses the string that comes out of xenbus_watch_wait_return. */
-static int parse_eventstr(const char* evstr, domid_t* domid, unsigned int* handle)
-{
- int ret;
- char cmd[40];
- char* err;
- char* value;
- unsigned int udomid = 0;
- tpmif_t* tpmif;
- /* First check for new frontends, this occurs when /backend/vtpm/<domid>/<handle> gets created. Note we what the sscanf to fail on the last %s */
- if (sscanf(evstr, "backend/vtpm/%u/%u/%40s", &udomid, handle, cmd) == 2) {
- *domid = udomid;
- /* Make sure the entry exists, if this event triggers because the entry dissapeared then ignore it */
- if((err = xenbus_read(XBT_NIL, evstr, &value))) {
- free(err);
- return EV_NONE;
- }
- free(value);
- /* Make sure the tpmif entry does not already exist, this should not happen */
- if((tpmif = get_tpmif(*domid, *handle)) != NULL) {
- TPMBACK_DEBUG("Duplicate tpm entries! %u %u\n", tpmif->domid, tpmif->handle);
- return EV_NONE;
- }
- return EV_NEWFE;
- } else if((ret = sscanf(evstr, "/local/domain/%u/device/vtpm/%u/%40s", &udomid, handle, cmd)) == 3) {
- *domid = udomid;
- if (!strcmp(cmd, "state"))
- return EV_STCHNG;
- }
- return EV_NONE;
-}
-
-void handle_backend_event(char* evstr) {
- tpmif_t* tpmif;
- domid_t domid;
- unsigned int handle;
- int event;
-
- TPMBACK_DEBUG("Xenbus Event: %s\n", evstr);
-
- event = parse_eventstr(evstr, &domid, &handle);
-
- switch(event) {
- case EV_NEWFE:
- if(new_tpmif(domid, handle) == NULL) {
- TPMBACK_ERR("Failed to create new tpm instance %u/%u\n", (unsigned int) domid, handle);
- }
- wake_up(&waitq);
- break;
- case EV_STCHNG:
- if((tpmif = get_tpmif(domid, handle))) {
- frontend_changed(tpmif);
- } else {
- TPMBACK_DEBUG("Event Received for non-existant tpm! instance=%u/%u xenbus_event=%s\n", (unsigned int) domid, handle, evstr);
- }
- break;
- }
-}
-
-/* Runs through the given path and creates events recursively
- * for all of its children.
- * @path - xenstore path to scan */
-static void generate_backend_events(const char* path)
-{
- char* err;
- int i, len;
- char **dirs;
- char *entry;
-
- if((err = xenbus_ls(XBT_NIL, path, &dirs)) != NULL) {
- free(err);
- return;
- }
-
- for(i = 0; dirs[i] != NULL; ++i) {
- len = strlen(path) + strlen(dirs[i]) + 2;
- entry = malloc(len);
- snprintf(entry, len, "%s/%s", path, dirs[i]);
-
- /* Generate and handle event for the entry itself */
- handle_backend_event(entry);
-
- /* Do children */
- generate_backend_events(entry);
-
- /* Cleanup */
- free(entry);
- free(dirs[i]);
- }
- free(dirs);
- return;
-}
-
-void* tpmback_get_opaque(domid_t domid, unsigned int handle)
-{
- tpmif_t* tpmif;
- if((tpmif = get_tpmif(domid, handle)) == NULL) {
- TPMBACK_DEBUG("get_opaque() failed, %u/%u is an invalid frontend\n", (unsigned int) domid, handle);
- return NULL;
- }
-
- return tpmif->opaque;
-}
-
-int tpmback_set_opaque(domid_t domid, unsigned int handle, void *opaque)
-{
- tpmif_t* tpmif;
- if((tpmif = get_tpmif(domid, handle)) == NULL) {
- TPMBACK_DEBUG("set_opaque() failed, %u/%u is an invalid frontend\n", (unsigned int) domid, handle);
- return -1;
- }
-
- tpmif->opaque = opaque;
- return 0;
-}
-
-unsigned char* tpmback_get_uuid(domid_t domid, unsigned int handle)
-{
- tpmif_t* tpmif;
- if((tpmif = get_tpmif(domid, handle)) == NULL) {
- TPMBACK_DEBUG("get_uuid() failed, %u/%u is an invalid frontend\n", (unsigned int) domid, handle);
- return NULL;
- }
-
- return tpmif->uuid;
-}
-
-int tpmback_get_peercontext(domid_t domid, unsigned int handle, void* buffer, int buflen)
-{
- tpmif_t* tpmif;
- if((tpmif = get_tpmif(domid, handle)) == NULL) {
- TPMBACK_DEBUG("get_uuid() failed, %u/%u is an invalid frontend\n", (unsigned int) domid, handle);
- return -1;
- }
-
- return evtchn_get_peercontext(tpmif->evtchn, buffer, buflen);
-}
-
-static void event_listener(void)
-{
- const char* bepath = "backend/vtpm";
- char **path;
- char* err;
-
- /* Setup the backend device watch */
- if((err = xenbus_watch_path_token(XBT_NIL, bepath, bepath, >pmdev.events)) != NULL) {
- TPMBACK_ERR("xenbus_watch_path_token(%s) failed with error %s!\n", bepath, err);
- free(err);
- goto egress;
- }
-
- /* Check for any frontends that connected before we set the watch.
- * This is almost guaranteed to happen if both domains are started
- * immediatly one after the other.
- * We do this by manually generating events on everything in the backend
- * path */
- generate_backend_events(bepath);
-
- /* Wait and listen for changes in frontend connections */
- while(1) {
- path = xenbus_wait_for_watch_return(>pmdev.events);
-
- /*If quit flag was set then exit */
- if(gtpmdev.flags & TPMIF_CLOSED) {
- TPMBACK_DEBUG("listener thread got quit event. Exiting..\n");
- free(path);
- break;
- }
- handle_backend_event(*path);
- free(path);
-
- }
-
- if((err = xenbus_unwatch_path_token(XBT_NIL, bepath, bepath)) != NULL) {
- free(err);
- }
-egress:
- return;
-}
-
-void event_thread(void* p) {
- event_listener();
-}
-
-void init_tpmback(void (*open_cb)(domid_t, unsigned int), void (*close_cb)(domid_t, unsigned int))
-{
- if(!globalinit) {
- init_waitqueue_head(&waitq);
- globalinit = 1;
- }
- printk("============= Init TPM BACK ================\n");
- gtpmdev.tpmlist = malloc(sizeof(tpmif_t*) * DEF_ARRAY_SIZE);
- gtpmdev.num_alloc = DEF_ARRAY_SIZE;
- gtpmdev.num_tpms = 0;
- gtpmdev.flags = 0;
-
- gtpmdev.open_callback = open_cb;
- gtpmdev.close_callback = close_cb;
-
- eventthread = create_thread("tpmback-listener", event_thread, NULL);
-
-}
-
-void shutdown_tpmback(void)
-{
- TPMBACK_LOG("Shutting down tpm backend\n");
- /* Set the quit flag */
- gtpmdev.flags = TPMIF_CLOSED;
-
- //printk("num tpms is %d\n", gtpmdev.num_tpms);
- /*Free all backend instances */
- while(gtpmdev.num_tpms) {
- free_tpmif(gtpmdev.tpmlist[0]);
- }
- free(gtpmdev.tpmlist);
- gtpmdev.tpmlist = NULL;
- gtpmdev.num_alloc = 0;
-
- /* Wake up anyone possibly waiting on the device and let them exit */
- wake_up(&waitq);
- schedule();
-}
-
-static void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, void *opaque)
-{
- tpmcmd->domid = domid;
- tpmcmd->locality = -1;
- tpmcmd->handle = handle;
- tpmcmd->opaque = opaque;
- tpmcmd->req = NULL;
- tpmcmd->req_len = 0;
- tpmcmd->resp = NULL;
- tpmcmd->resp_len = 0;
-}
-
-tpmcmd_t* get_request(tpmif_t* tpmif) {
- tpmcmd_t* cmd;
- tpmif_shared_page_t *shr;
- unsigned int offset;
- int flags;
-#ifdef TPMBACK_PRINT_DEBUG
- int i;
-#endif
-
- local_irq_save(flags);
-
- /* Allocate the cmd object to hold the data */
- if((cmd = malloc(sizeof(*cmd))) == NULL) {
- goto error;
- }
- init_tpmcmd(cmd, tpmif->domid, tpmif->handle, tpmif->opaque);
-
- shr = tpmif->page;
- cmd->req_len = shr->length;
- cmd->locality = shr->locality;
- offset = sizeof(*shr) + 4*shr->nr_extra_pages;
- if (offset > PAGE_SIZE || offset + cmd->req_len > PAGE_SIZE) {
- TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
- goto error;
- }
- /* Allocate the buffer */
- if(cmd->req_len) {
- if((cmd->req = malloc(cmd->req_len)) == NULL) {
- goto error;
- }
- }
- /* Copy the bits from the shared page(s) */
- memcpy(cmd->req, offset + (uint8_t*)shr, cmd->req_len);
-
-#ifdef TPMBACK_PRINT_DEBUG
- TPMBACK_DEBUG("Received Tpm Command from %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->req_len);
- for(i = 0; i < cmd->req_len; ++i) {
- if (!(i % 30)) {
- TPMBACK_DEBUG_MORE("\n");
- }
- TPMBACK_DEBUG_MORE("%02hhX ", cmd->req[i]);
- }
- TPMBACK_DEBUG_MORE("\n\n");
-#endif
-
- local_irq_restore(flags);
- return cmd;
-error:
- if(cmd != NULL) {
- if (cmd->req != NULL) {
- free(cmd->req);
- cmd->req = NULL;
- }
- free(cmd);
- cmd = NULL;
- }
- local_irq_restore(flags);
- return NULL;
-
-}
-
-void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
-{
- tpmif_shared_page_t *shr;
- unsigned int offset;
- int flags;
-#ifdef TPMBACK_PRINT_DEBUG
-int i;
-#endif
-
- local_irq_save(flags);
-
- shr = tpmif->page;
- shr->length = cmd->resp_len;
-
- offset = sizeof(*shr) + 4*shr->nr_extra_pages;
- if (offset > PAGE_SIZE || offset + cmd->resp_len > PAGE_SIZE) {
- TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
- goto error;
- }
- memcpy(offset + (uint8_t*)shr, cmd->resp, cmd->resp_len);
-
-#ifdef TPMBACK_PRINT_DEBUG
- TPMBACK_DEBUG("Sent response to %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->resp_len);
- for(i = 0; i < cmd->resp_len; ++i) {
- if (!(i % 30)) {
- TPMBACK_DEBUG_MORE("\n");
- }
- TPMBACK_DEBUG_MORE("%02hhX ", cmd->resp[i]);
- }
- TPMBACK_DEBUG_MORE("\n\n");
-#endif
- /* clear the ready flag and send the event channel notice to the frontend */
- tpmif_req_finished(tpmif);
- barrier();
- shr->state = TPMIF_STATE_FINISH;
- wmb();
- notify_remote_via_evtchn(tpmif->evtchn);
-error:
- local_irq_restore(flags);
- return;
-}
-
-tpmcmd_t* tpmback_req_any(void)
-{
- int i;
- /* Block until something has a request */
- wait_event(waitq, (gtpmdev.flags & (TPMIF_REQ_READY | TPMIF_CLOSED)));
-
- /* Check if were shutting down */
- if(gtpmdev.flags & TPMIF_CLOSED) {
- /* if something was waiting for us to give up the queue so it can shutdown, let it finish */
- schedule();
- return NULL;
- }
-
- for(i = 0; i < gtpmdev.num_tpms; ++i) {
- if(gtpmdev.tpmlist[i]->flags & TPMIF_REQ_READY) {
- return get_request(gtpmdev.tpmlist[i]);
- }
- }
-
- TPMBACK_ERR("backend request ready flag was set but no interfaces were actually ready\n");
- return NULL;
-}
-
-tpmcmd_t* tpmback_req(domid_t domid, unsigned int handle)
-{
- tpmif_t* tpmif;
- tpmif = get_tpmif(domid, handle);
- if(tpmif == NULL) {
- return NULL;
- }
-
- wait_event(waitq, (tpmif->flags & (TPMIF_REQ_READY | TPMIF_CLOSED) || gtpmdev.flags & TPMIF_CLOSED));
-
- /* Check if were shutting down */
- if(tpmif->flags & TPMIF_CLOSED || gtpmdev.flags & TPMIF_CLOSED) {
- /* if something was waiting for us to give up the queue so it can free this instance, let it finish */
- schedule();
- return NULL;
- }
-
- return get_request(tpmif);
-}
-
-void tpmback_resp(tpmcmd_t* tpmcmd)
-{
- tpmif_t* tpmif;
-
- /* Get the associated interface, if it doesnt exist then just quit */
- tpmif = get_tpmif(tpmcmd->domid, tpmcmd->handle);
- if(tpmif == NULL) {
- TPMBACK_ERR("Tried to send a reponse to non existant frontend %u/%u\n", (unsigned int) tpmcmd->domid, tpmcmd->handle);
- goto end;
- }
-
- if(!(tpmif->flags & TPMIF_REQ_READY)) {
- TPMBACK_ERR("Tried to send response to a frontend that was not waiting for one %u/%u\n", (unsigned int) tpmcmd->domid, tpmcmd->handle);
- goto end;
- }
-
- /* Send response to frontend */
- send_response(tpmcmd, tpmif);
-
-end:
- if(tpmcmd->req != NULL) {
- free(tpmcmd->req);
- }
- free(tpmcmd);
- return;
-}
-
-int tpmback_wait_for_frontend_connect(domid_t *domid, unsigned int *handle)
-{
- tpmif_t* tpmif;
- int flags;
- wait_event(waitq, ((gtpmdev.num_tpms > 0) || gtpmdev.flags & TPMIF_CLOSED));
- if(gtpmdev.flags & TPMIF_CLOSED) {
- return -1;
- }
- local_irq_save(flags);
- tpmif = gtpmdev.tpmlist[0];
- *domid = tpmif->domid;
- *handle = tpmif->handle;
- local_irq_restore(flags);
-
- return 0;
-}
-
-int tpmback_num_frontends(void)
-{
- return gtpmdev.num_tpms;
-}
+++ /dev/null
-/*
- * Copyright (c) 2010-2012 United States Government, as represented by
- * the Secretary of Defense. All rights reserved.
- *
- * This code has been derived from drivers/char/tpm_vtpm.c
- * from the xen 2.6.18 linux kernel
- *
- * Copyright (C) 2006 IBM Corporation
- *
- * This code has also been derived from drivers/char/tpm_xen.c
- * from the xen 2.6.18 linux kernel
- *
- * Copyright (c) 2005, IBM Corporation
- *
- * which was itself derived from drivers/xen/netfront/netfront.c
- * from the linux kernel
- *
- * Copyright (c) 2002-2004, K A Fraser
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- */
-#include <mini-os/os.h>
-#include <mini-os/xenbus.h>
-#include <mini-os/xmalloc.h>
-#include <mini-os/events.h>
-#include <mini-os/wait.h>
-#include <mini-os/gnttab.h>
-#include <xen/io/xenbus.h>
-#include <xen/io/tpmif.h>
-#include <mini-os/tpmfront.h>
-#include <mini-os/lib.h>
-#include <fcntl.h>
-
-//#define TPMFRONT_PRINT_DEBUG
-#ifdef TPMFRONT_PRINT_DEBUG
-#define TPMFRONT_DEBUG(fmt,...) printk("Tpmfront:Debug("__FILE__":%d) " fmt, __LINE__, ##__VA_ARGS__)
-#define TPMFRONT_DEBUG_MORE(fmt,...) printk(fmt, ##__VA_ARGS__)
-#else
-#define TPMFRONT_DEBUG(fmt,...)
-#endif
-#define TPMFRONT_ERR(fmt,...) printk("Tpmfront:Error " fmt, ##__VA_ARGS__)
-#define TPMFRONT_LOG(fmt,...) printk("Tpmfront:Info " fmt, ##__VA_ARGS__)
-
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-
-void tpmfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data) {
- struct tpmfront_dev* dev = (struct tpmfront_dev*) data;
- tpmif_shared_page_t *shr = dev->page;
- /*If we get a response when we didnt make a request, just ignore it */
- if(!dev->waiting) {
- return;
- }
-
- switch (shr->state) {
- case TPMIF_STATE_FINISH: /* request was completed */
- case TPMIF_STATE_IDLE: /* request was cancelled */
- break;
- default:
- /* Spurious wakeup; do nothing, request is still pending */
- return;
- }
-
- dev->waiting = 0;
-#ifdef HAVE_LIBC
- if(dev->fd >= 0) {
- files[dev->fd].read = 1;
- }
-#endif
- wake_up(&dev->waitq);
-}
-
-static int publish_xenbus(struct tpmfront_dev* dev) {
- xenbus_transaction_t xbt;
- int retry;
- char* err;
- /* Write the grant reference and event channel to xenstore */
-again:
- if((err = xenbus_transaction_start(&xbt))) {
- TPMFRONT_ERR("Unable to start xenbus transaction, error was %s\n", err);
- free(err);
- return -1;
- }
-
- if((err = xenbus_printf(xbt, dev->nodename, "ring-ref", "%u", (unsigned int) dev->ring_ref))) {
- TPMFRONT_ERR("Unable to write %s/ring-ref, error was %s\n", dev->nodename, err);
- free(err);
- goto abort_transaction;
- }
-
- if((err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", (unsigned int) dev->evtchn))) {
- TPMFRONT_ERR("Unable to write %s/event-channel, error was %s\n", dev->nodename, err);
- free(err);
- goto abort_transaction;
- }
-
- if((err = xenbus_transaction_end(xbt, 0, &retry))) {
- TPMFRONT_ERR("Unable to complete xenbus transaction, error was %s\n", err);
- free(err);
- return -1;
- }
- if(retry) {
- goto again;
- }
-
- return 0;
-abort_transaction:
- if((err = xenbus_transaction_end(xbt, 1, &retry))) {
- free(err);
- }
- return -1;
-}
-
-static int wait_for_backend_connect(xenbus_event_queue* events, char* path)
-{
- int state;
-
- TPMFRONT_LOG("Waiting for backend connection..\n");
- /* Wait for the backend to connect */
- while(1) {
- state = xenbus_read_integer(path);
- if ( state < 0)
- state = XenbusStateUnknown;
- switch(state) {
- /* Bad states, we quit with error */
- case XenbusStateUnknown:
- case XenbusStateClosing:
- case XenbusStateClosed:
- TPMFRONT_ERR("Unable to connect to backend\n");
- return -1;
- /* If backend is connected then break out of loop */
- case XenbusStateConnected:
- TPMFRONT_LOG("Backend Connected\n");
- return 0;
- default:
- xenbus_wait_for_watch(events);
- }
- }
-
-}
-
-static int wait_for_backend_closed(xenbus_event_queue* events, char* path)
-{
- int state;
-
- TPMFRONT_LOG("Waiting for backend to close..\n");
- while(1) {
- state = xenbus_read_integer(path);
- if ( state < 0)
- state = XenbusStateUnknown;
- switch(state) {
- case XenbusStateUnknown:
- TPMFRONT_ERR("Backend Unknown state, forcing shutdown\n");
- return -1;
- case XenbusStateClosed:
- TPMFRONT_LOG("Backend Closed\n");
- return 0;
- case XenbusStateInitWait:
- TPMFRONT_LOG("Backend Closed (waiting for reconnect)\n");
- return 0;
- default:
- xenbus_wait_for_watch(events);
- }
- }
-
-}
-
-static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState state) {
- char* err;
- int ret = 0;
- xenbus_event_queue events = NULL;
- char path[512];
-
- snprintf(path, 512, "%s/state", dev->bepath);
- /*Setup the watch to wait for the backend */
- if((err = xenbus_watch_path_token(XBT_NIL, path, path, &events))) {
- TPMFRONT_ERR("Could not set a watch on %s, error was %s\n", path, err);
- free(err);
- return -1;
- }
-
- /* Do the actual wait loop now */
- switch(state) {
- case XenbusStateConnected:
- ret = wait_for_backend_connect(&events, path);
- break;
- case XenbusStateClosed:
- ret = wait_for_backend_closed(&events, path);
- break;
- default:
- TPMFRONT_ERR("Bad wait state %d, ignoring\n", state);
- }
-
- if((err = xenbus_unwatch_path_token(XBT_NIL, path, path))) {
- TPMFRONT_ERR("Unable to unwatch %s, error was %s, ignoring..\n", path, err);
- free(err);
- }
- return ret;
-}
-
-static int tpmfront_connect(struct tpmfront_dev* dev)
-{
- char* err;
- /* Create shared page */
- dev->page = (tpmif_shared_page_t *)alloc_page();
- if(dev->page == NULL) {
- TPMFRONT_ERR("Unable to allocate page for shared memory\n");
- goto error;
- }
- memset(dev->page, 0, PAGE_SIZE);
- dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->page), 0);
- TPMFRONT_DEBUG("grant ref is %lu\n", (unsigned long) dev->ring_ref);
-
- /*Create event channel */
- if(evtchn_alloc_unbound(dev->bedomid, tpmfront_handler, dev, &dev->evtchn)) {
- TPMFRONT_ERR("Unable to allocate event channel\n");
- goto error_postmap;
- }
- unmask_evtchn(dev->evtchn);
- TPMFRONT_DEBUG("event channel is %lu\n", (unsigned long) dev->evtchn);
-
- /* Write the entries to xenstore */
- if(publish_xenbus(dev)) {
- goto error_postevtchn;
- }
-
- /* Change state to connected */
- dev->state = XenbusStateConnected;
-
- /* Tell the backend that we are ready */
- if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", dev->state))) {
- TPMFRONT_ERR("Unable to write to xenstore %s/state, value=%u", dev->nodename, XenbusStateConnected);
- free(err);
- goto error;
- }
-
- return 0;
-error_postevtchn:
- mask_evtchn(dev->evtchn);
- unbind_evtchn(dev->evtchn);
-error_postmap:
- gnttab_end_access(dev->ring_ref);
- free_page(dev->page);
-error:
- return -1;
-}
-
-struct tpmfront_dev* init_tpmfront(const char* _nodename)
-{
- struct tpmfront_dev* dev;
- const char* nodename;
- char path[512];
- char* value, *err;
- unsigned long long ival;
-
- printk("============= Init TPM Front ================\n");
-
- dev = malloc(sizeof(struct tpmfront_dev));
- memset(dev, 0, sizeof(struct tpmfront_dev));
-
-#ifdef HAVE_LIBC
- dev->fd = -1;
-#endif
-
- nodename = _nodename ? _nodename : "device/vtpm/0";
- dev->nodename = strdup(nodename);
-
- init_waitqueue_head(&dev->waitq);
-
- /* Get backend domid */
- snprintf(path, 512, "%s/backend-id", dev->nodename);
- if((err = xenbus_read(XBT_NIL, path, &value))) {
- TPMFRONT_ERR("Unable to read %s during tpmfront initialization! error = %s\n", path, err);
- free(err);
- goto error;
- }
- if(sscanf(value, "%llu", &ival) != 1) {
- TPMFRONT_ERR("%s has non-integer value (%s)\n", path, value);
- free(value);
- goto error;
- }
- free(value);
- dev->bedomid = ival;
-
- /* Get backend xenstore path */
- snprintf(path, 512, "%s/backend", dev->nodename);
- if((err = xenbus_read(XBT_NIL, path, &dev->bepath))) {
- TPMFRONT_ERR("Unable to read %s during tpmfront initialization! error = %s\n", path, err);
- free(err);
- goto error;
- }
-
- /* Publish protocol v2 feature */
- snprintf(path, 512, "%s/feature-protocol-v2", dev->nodename);
- if ((err = xenbus_write(XBT_NIL, path, "1")))
- {
- TPMFRONT_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
- free(err);
- goto error;
- }
-
- /* Create and publish grant reference and event channel */
- if (tpmfront_connect(dev)) {
- goto error;
- }
-
- /* Wait for backend to connect */
- if( wait_for_backend_state_changed(dev, XenbusStateConnected)) {
- goto error;
- }
-
- /* Ensure backend is also using protocol v2 */
- snprintf(path, 512, "%s/feature-protocol-v2", dev->bepath);
- if((err = xenbus_read(XBT_NIL, path, &value))) {
- TPMFRONT_ERR("Unable to read %s during tpmfront initialization! error = %s\n", path, err);
- free(err);
- goto error;
- }
- if(strcmp(value, "1")) {
- TPMFRONT_ERR("%s has an invalid value (%s)\n", path, value);
- free(value);
- goto error;
- }
- free(value);
-
- TPMFRONT_LOG("Initialization Completed successfully\n");
-
- return dev;
-
-error:
- shutdown_tpmfront(dev);
- return NULL;
-}
-void shutdown_tpmfront(struct tpmfront_dev* dev)
-{
- char* err;
- char path[512];
- if(dev == NULL) {
- return;
- }
- TPMFRONT_LOG("Shutting down tpmfront\n");
- /* disconnect */
- if(dev->state == XenbusStateConnected) {
- /* Tell backend we are closing */
- dev->state = XenbusStateClosing;
- if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", (unsigned int) dev->state))) {
- TPMFRONT_ERR("Unable to write to %s, error was %s", dev->nodename, err);
- free(err);
- }
-
- /* Clean up xenstore entries */
- snprintf(path, 512, "%s/event-channel", dev->nodename);
- if((err = xenbus_rm(XBT_NIL, path))) {
- free(err);
- }
- snprintf(path, 512, "%s/ring-ref", dev->nodename);
- if((err = xenbus_rm(XBT_NIL, path))) {
- free(err);
- }
-
- /* Tell backend we are closed */
- dev->state = XenbusStateClosed;
- if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", (unsigned int) dev->state))) {
- TPMFRONT_ERR("Unable to write to %s, error was %s", dev->nodename, err);
- free(err);
- }
-
- /* Wait for the backend to close and unmap shared pages, ignore any errors */
- wait_for_backend_state_changed(dev, XenbusStateClosed);
-
- /* Prepare for a later reopen (possibly by a kexec'd kernel) */
- dev->state = XenbusStateInitialising;
- if((err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%u", (unsigned int) dev->state))) {
- TPMFRONT_ERR("Unable to write to %s, error was %s", dev->nodename, err);
- free(err);
- }
-
- /* Close event channel and unmap shared page */
- mask_evtchn(dev->evtchn);
- unbind_evtchn(dev->evtchn);
- gnttab_end_access(dev->ring_ref);
-
- free_page(dev->page);
- }
-
- /* Cleanup memory usage */
- if(dev->respbuf) {
- free(dev->respbuf);
- }
- if(dev->bepath) {
- free(dev->bepath);
- }
- if(dev->nodename) {
- free(dev->nodename);
- }
- free(dev);
-}
-
-int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
-{
- unsigned int offset;
- tpmif_shared_page_t *shr = NULL;
-#ifdef TPMFRONT_PRINT_DEBUG
- int i;
-#endif
- /* Error Checking */
- if(dev == NULL || dev->state != XenbusStateConnected) {
- TPMFRONT_ERR("Tried to send message through disconnected frontend\n");
- return -1;
- }
- shr = dev->page;
-
-#ifdef TPMFRONT_PRINT_DEBUG
- TPMFRONT_DEBUG("Sending Msg to backend size=%u", (unsigned int) length);
- for(i = 0; i < length; ++i) {
- if(!(i % 30)) {
- TPMFRONT_DEBUG_MORE("\n");
- }
- TPMFRONT_DEBUG_MORE("%02X ", msg[i]);
- }
- TPMFRONT_DEBUG_MORE("\n");
-#endif
-
- /* Copy to shared pages now */
- offset = sizeof(*shr);
- if (length + offset > PAGE_SIZE) {
- TPMFRONT_ERR("Message too long for shared page\n");
- return -1;
- }
- memcpy(offset + (uint8_t*)shr, msg, length);
- shr->length = length;
- barrier();
- shr->state = TPMIF_STATE_SUBMIT;
-
- dev->waiting = 1;
- dev->resplen = 0;
-#ifdef HAVE_LIBC
- if(dev->fd >= 0) {
- files[dev->fd].read = 0;
- files[dev->fd].tpmfront.respgot = 0;
- files[dev->fd].tpmfront.offset = 0;
- }
-#endif
- wmb();
- notify_remote_via_evtchn(dev->evtchn);
- return 0;
-}
-int tpmfront_recv(struct tpmfront_dev* dev, uint8_t** msg, size_t *length)
-{
- unsigned int offset;
- tpmif_shared_page_t *shr = NULL;
-#ifdef TPMFRONT_PRINT_DEBUG
-int i;
-#endif
- if(dev == NULL || dev->state != XenbusStateConnected) {
- TPMFRONT_ERR("Tried to receive message from disconnected frontend\n");
- return -1;
- }
- /*Wait for the response */
- wait_event(dev->waitq, (!dev->waiting));
- shr = dev->page;
-
- /* Initialize */
- *msg = NULL;
- *length = 0;
- offset = sizeof(*shr);
-
- if (shr->state != TPMIF_STATE_FINISH)
- goto quit;
-
- *length = shr->length;
-
- if (*length + offset > PAGE_SIZE) {
- TPMFRONT_ERR("Reply too long for shared page\n");
- return -1;
- }
-
- /* Alloc the buffer */
- if(dev->respbuf) {
- free(dev->respbuf);
- }
- *msg = dev->respbuf = malloc(*length);
- dev->resplen = *length;
-
- /* Copy the bits */
- memcpy(*msg, offset + (uint8_t*)shr, *length);
-
-#ifdef TPMFRONT_PRINT_DEBUG
- TPMFRONT_DEBUG("Received response from backend size=%u", (unsigned int) *length);
- for(i = 0; i < *length; ++i) {
- if(!(i % 30)) {
- TPMFRONT_DEBUG_MORE("\n");
- }
- TPMFRONT_DEBUG_MORE("%02X ", (*msg)[i]);
- }
- TPMFRONT_DEBUG_MORE("\n");
-#endif
-#ifdef HAVE_LIBC
- if(dev->fd >= 0) {
- files[dev->fd].tpmfront.respgot = 1;
- }
-#endif
-quit:
- return 0;
-}
-
-int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen)
-{
- int rc;
- if((rc = tpmfront_send(dev, req, reqlen))) {
- return rc;
- }
- if((rc = tpmfront_recv(dev, resp, resplen))) {
- return rc;
- }
-
- return 0;
-}
-
-int tpmfront_set_locality(struct tpmfront_dev* dev, int locality)
-{
- if (!dev || !dev->page)
- return -1;
- dev->page->locality = locality;
- return 0;
-}
-
-#ifdef HAVE_LIBC
-#include <errno.h>
-int tpmfront_open(struct tpmfront_dev* dev)
-{
- /* Silently prevent multiple opens */
- if(dev->fd != -1) {
- return dev->fd;
- }
-
- dev->fd = alloc_fd(FTYPE_TPMFRONT);
- printk("tpmfront_open(%s) -> %d\n", dev->nodename, dev->fd);
- files[dev->fd].tpmfront.dev = dev;
- files[dev->fd].tpmfront.offset = 0;
- files[dev->fd].tpmfront.respgot = 0;
- return dev->fd;
-}
-
-int tpmfront_posix_write(int fd, const uint8_t* buf, size_t count)
-{
- int rc;
- struct tpmfront_dev* dev;
- dev = files[fd].tpmfront.dev;
-
- if(count == 0) {
- return 0;
- }
-
- /* Return an error if we are already processing a command */
- if(dev->waiting) {
- errno = EINPROGRESS;
- return -1;
- }
- /* Send the command now */
- if((rc = tpmfront_send(dev, buf, count)) != 0) {
- errno = EIO;
- return -1;
- }
- return count;
-}
-
-int tpmfront_posix_read(int fd, uint8_t* buf, size_t count)
-{
- int rc;
- uint8_t* dummybuf;
- size_t dummysz;
- struct tpmfront_dev* dev;
-
- dev = files[fd].tpmfront.dev;
-
- if(count == 0) {
- return 0;
- }
-
- /* get the response if we haven't already */
- if(files[dev->fd].tpmfront.respgot == 0) {
- if ((rc = tpmfront_recv(dev, &dummybuf, &dummysz)) != 0) {
- errno = EIO;
- return -1;
- }
- }
-
- /* handle EOF case */
- if(files[dev->fd].tpmfront.offset >= dev->resplen) {
- return 0;
- }
-
- /* Compute the number of bytes and do the copy operation */
- if((rc = min(count, dev->resplen - files[dev->fd].tpmfront.offset)) != 0) {
- memcpy(buf, dev->respbuf + files[dev->fd].tpmfront.offset, rc);
- files[dev->fd].tpmfront.offset += rc;
- }
-
- return rc;
-}
-
-int tpmfront_posix_fstat(int fd, struct stat* buf)
-{
- uint8_t* dummybuf;
- size_t dummysz;
- int rc;
- struct tpmfront_dev* dev = files[fd].tpmfront.dev;
-
- /* If we have a response waiting, then read it now from the backend
- * so we can get its length*/
- if(dev->waiting || (files[dev->fd].read == 1 && !files[dev->fd].tpmfront.respgot)) {
- if ((rc = tpmfront_recv(dev, &dummybuf, &dummysz)) != 0) {
- errno = EIO;
- return -1;
- }
- }
-
- buf->st_mode = O_RDWR;
- buf->st_uid = 0;
- buf->st_gid = 0;
- buf->st_size = dev->resplen;
- buf->st_atime = buf->st_mtime = buf->st_ctime = time(NULL);
-
- return 0;
-}
-
-
-#endif
+++ /dev/null
-/*
- ****************************************************************************
- * (C) 2006 - Cambridge University
- ****************************************************************************
- *
- * File: xenbus.c
- * Author: Steven Smith (sos22@cam.ac.uk)
- * Changes: Grzegorz Milos (gm281@cam.ac.uk)
- * Changes: John D. Ramsdell
- *
- * Date: Jun 2006, chages Aug 2005
- *
- * Environment: Xen Minimal OS
- * Description: Minimal implementation of xenbus
- *
- ****************************************************************************
- **/
-#include <inttypes.h>
-#include <mini-os/os.h>
-#include <mini-os/mm.h>
-#include <mini-os/traps.h>
-#include <mini-os/lib.h>
-#include <mini-os/xenbus.h>
-#include <mini-os/events.h>
-#include <mini-os/errno.h>
-#include <mini-os/sched.h>
-#include <mini-os/wait.h>
-#include <xen/io/xs_wire.h>
-#include <mini-os/spinlock.h>
-#include <mini-os/xmalloc.h>
-
-#define min(x,y) ({ \
- typeof(x) tmpx = (x); \
- typeof(y) tmpy = (y); \
- tmpx < tmpy ? tmpx : tmpy; \
- })
-
-#ifdef XENBUS_DEBUG
-#define DEBUG(_f, _a...) \
- printk("MINI_OS(file=xenbus.c, line=%d) " _f , __LINE__, ## _a)
-#else
-#define DEBUG(_f, _a...) ((void)0)
-#endif
-
-static struct xenstore_domain_interface *xenstore_buf;
-static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
-DECLARE_WAIT_QUEUE_HEAD(xenbus_watch_queue);
-
-xenbus_event_queue xenbus_events;
-static struct watch {
- char *token;
- xenbus_event_queue *events;
- struct watch *next;
-} *watches;
-struct xenbus_req_info
-{
- int in_use:1;
- struct wait_queue_head waitq;
- void *reply;
-};
-
-#define NR_REQS 32
-static struct xenbus_req_info req_info[NR_REQS];
-
-static void memcpy_from_ring(const void *Ring,
- void *Dest,
- int off,
- int len)
-{
- int c1, c2;
- const char *ring = Ring;
- char *dest = Dest;
- c1 = min(len, XENSTORE_RING_SIZE - off);
- c2 = len - c1;
- memcpy(dest, ring + off, c1);
- memcpy(dest + c1, ring, c2);
-}
-
-char **xenbus_wait_for_watch_return(xenbus_event_queue *queue)
-{
- struct xenbus_event *event;
- DEFINE_WAIT(w);
- if (!queue)
- queue = &xenbus_events;
- while (!(event = *queue)) {
- add_waiter(w, xenbus_watch_queue);
- schedule();
- }
- remove_waiter(w, xenbus_watch_queue);
- *queue = event->next;
- return &event->path;
-}
-
-void xenbus_wait_for_watch(xenbus_event_queue *queue)
-{
- char **ret;
- if (!queue)
- queue = &xenbus_events;
- ret = xenbus_wait_for_watch_return(queue);
- if (ret)
- free(ret);
- else
- printk("unexpected path returned by watch\n");
-}
-
-char* xenbus_wait_for_value(const char* path, const char* value, xenbus_event_queue *queue)
-{
- if (!queue)
- queue = &xenbus_events;
- for(;;)
- {
- char *res, *msg;
- int r;
-
- msg = xenbus_read(XBT_NIL, path, &res);
- if(msg) return msg;
-
- r = strcmp(value,res);
- free(res);
-
- if(r==0) break;
- else xenbus_wait_for_watch(queue);
- }
- return NULL;
-}
-
-char *xenbus_switch_state(xenbus_transaction_t xbt, const char* path, XenbusState state)
-{
- char *current_state;
- char *msg = NULL;
- char *msg2 = NULL;
- char value[2];
- XenbusState rs;
- int xbt_flag = 0;
- int retry = 0;
-
- do {
- if (xbt == XBT_NIL) {
- msg = xenbus_transaction_start(&xbt);
- if (msg) goto exit;
- xbt_flag = 1;
- }
-
- msg = xenbus_read(xbt, path, ¤t_state);
- if (msg) goto exit;
-
- rs = (XenbusState) (current_state[0] - '0');
- free(current_state);
- if (rs == state) {
- msg = NULL;
- goto exit;
- }
-
- snprintf(value, 2, "%d", state);
- msg = xenbus_write(xbt, path, value);
-
-exit:
- if (xbt_flag) {
- msg2 = xenbus_transaction_end(xbt, 0, &retry);
- xbt = XBT_NIL;
- }
- if (msg == NULL && msg2 != NULL)
- msg = msg2;
- } while (retry);
-
- return msg;
-}
-
-char *xenbus_wait_for_state_change(const char* path, XenbusState *state, xenbus_event_queue *queue)
-{
- if (!queue)
- queue = &xenbus_events;
- for(;;)
- {
- char *res, *msg;
- XenbusState rs;
-
- msg = xenbus_read(XBT_NIL, path, &res);
- if(msg) return msg;
-
- rs = (XenbusState) (res[0] - 48);
- free(res);
-
- if (rs == *state)
- xenbus_wait_for_watch(queue);
- else {
- *state = rs;
- break;
- }
- }
- return NULL;
-}
-
-
-static void xenbus_thread_func(void *ign)
-{
- struct xsd_sockmsg msg;
- unsigned prod = xenstore_buf->rsp_prod;
-
- for (;;)
- {
- wait_event(xb_waitq, prod != xenstore_buf->rsp_prod);
- while (1)
- {
- prod = xenstore_buf->rsp_prod;
- DEBUG("Rsp_cons %d, rsp_prod %d.\n", xenstore_buf->rsp_cons,
- xenstore_buf->rsp_prod);
- if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg))
- break;
- rmb();
- memcpy_from_ring(xenstore_buf->rsp,
- &msg,
- MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
- sizeof(msg));
- DEBUG("Msg len %d, %d avail, id %d.\n",
- msg.len + sizeof(msg),
- xenstore_buf->rsp_prod - xenstore_buf->rsp_cons,
- msg.req_id);
- if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons <
- sizeof(msg) + msg.len)
- break;
-
- DEBUG("Message is good.\n");
-
- if(msg.type == XS_WATCH_EVENT)
- {
- struct xenbus_event *event = malloc(sizeof(*event) + msg.len);
- xenbus_event_queue *events = NULL;
- char *data = (char*)event + sizeof(*event);
- struct watch *watch;
-
- memcpy_from_ring(xenstore_buf->rsp,
- data,
- MASK_XENSTORE_IDX(xenstore_buf->rsp_cons + sizeof(msg)),
- msg.len);
-
- event->path = data;
- event->token = event->path + strlen(event->path) + 1;
-
- xenstore_buf->rsp_cons += msg.len + sizeof(msg);
-
- for (watch = watches; watch; watch = watch->next)
- if (!strcmp(watch->token, event->token)) {
- events = watch->events;
- break;
- }
-
- if (events) {
- event->next = *events;
- *events = event;
- wake_up(&xenbus_watch_queue);
- } else {
- printk("unexpected watch token %s\n", event->token);
- free(event);
- }
- }
-
- else
- {
- req_info[msg.req_id].reply = malloc(sizeof(msg) + msg.len);
- memcpy_from_ring(xenstore_buf->rsp,
- req_info[msg.req_id].reply,
- MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
- msg.len + sizeof(msg));
- xenstore_buf->rsp_cons += msg.len + sizeof(msg);
- wake_up(&req_info[msg.req_id].waitq);
- }
- }
- }
-}
-
-static void xenbus_evtchn_handler(evtchn_port_t port, struct pt_regs *regs,
- void *ign)
-{
- wake_up(&xb_waitq);
-}
-
-static int nr_live_reqs;
-static DEFINE_SPINLOCK(req_lock);
-static DECLARE_WAIT_QUEUE_HEAD(req_wq);
-
-/* Release a xenbus identifier */
-static void release_xenbus_id(int id)
-{
- BUG_ON(!req_info[id].in_use);
- spin_lock(&req_lock);
- req_info[id].in_use = 0;
- nr_live_reqs--;
- req_info[id].in_use = 0;
- if (nr_live_reqs == NR_REQS - 1)
- wake_up(&req_wq);
- spin_unlock(&req_lock);
-}
-
-/* Allocate an identifier for a xenbus request. Blocks if none are
- available. */
-static int allocate_xenbus_id(void)
-{
- static int probe;
- int o_probe;
-
- while (1)
- {
- spin_lock(&req_lock);
- if (nr_live_reqs < NR_REQS)
- break;
- spin_unlock(&req_lock);
- wait_event(req_wq, (nr_live_reqs < NR_REQS));
- }
-
- o_probe = probe;
- for (;;)
- {
- if (!req_info[o_probe].in_use)
- break;
- o_probe = (o_probe + 1) % NR_REQS;
- BUG_ON(o_probe == probe);
- }
- nr_live_reqs++;
- req_info[o_probe].in_use = 1;
- probe = (o_probe + 1) % NR_REQS;
- spin_unlock(&req_lock);
- init_waitqueue_head(&req_info[o_probe].waitq);
-
- return o_probe;
-}
-
-/* Initialise xenbus. */
-void init_xenbus(void)
-{
- int err;
- DEBUG("init_xenbus called.\n");
- xenstore_buf = mfn_to_virt(start_info.store_mfn);
- create_thread("xenstore", xenbus_thread_func, NULL);
- DEBUG("buf at %p.\n", xenstore_buf);
- err = bind_evtchn(start_info.store_evtchn,
- xenbus_evtchn_handler,
- NULL);
- unmask_evtchn(start_info.store_evtchn);
- printk("xenbus initialised on irq %d mfn %#lx\n",
- err, start_info.store_mfn);
-}
-
-void fini_xenbus(void)
-{
-}
-
-/* Send data to xenbus. This can block. All of the requests are seen
- by xenbus as if sent atomically. The header is added
- automatically, using type %type, req_id %req_id, and trans_id
- %trans_id. */
-static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
- const struct write_req *req, int nr_reqs)
-{
- XENSTORE_RING_IDX prod;
- int r;
- int len = 0;
- const struct write_req *cur_req;
- int req_off;
- int total_off;
- int this_chunk;
- struct xsd_sockmsg m = {.type = type, .req_id = req_id,
- .tx_id = trans_id };
- struct write_req header_req = { &m, sizeof(m) };
-
- for (r = 0; r < nr_reqs; r++)
- len += req[r].len;
- m.len = len;
- len += sizeof(m);
-
- cur_req = &header_req;
-
- BUG_ON(len > XENSTORE_RING_SIZE);
- /* Wait for the ring to drain to the point where we can send the
- message. */
- prod = xenstore_buf->req_prod;
- if (prod + len - xenstore_buf->req_cons > XENSTORE_RING_SIZE)
- {
- /* Wait for there to be space on the ring */
- DEBUG("prod %d, len %d, cons %d, size %d; waiting.\n",
- prod, len, xenstore_buf->req_cons, XENSTORE_RING_SIZE);
- wait_event(xb_waitq,
- xenstore_buf->req_prod + len - xenstore_buf->req_cons <=
- XENSTORE_RING_SIZE);
- DEBUG("Back from wait.\n");
- prod = xenstore_buf->req_prod;
- }
-
- /* We're now guaranteed to be able to send the message without
- overflowing the ring. Do so. */
- total_off = 0;
- req_off = 0;
- while (total_off < len)
- {
- this_chunk = min(cur_req->len - req_off,
- XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
- memcpy((char *)xenstore_buf->req + MASK_XENSTORE_IDX(prod),
- (char *)cur_req->data + req_off, this_chunk);
- prod += this_chunk;
- req_off += this_chunk;
- total_off += this_chunk;
- if (req_off == cur_req->len)
- {
- req_off = 0;
- if (cur_req == &header_req)
- cur_req = req;
- else
- cur_req++;
- }
- }
-
- DEBUG("Complete main loop of xb_write.\n");
- BUG_ON(req_off != 0);
- BUG_ON(total_off != len);
- BUG_ON(prod > xenstore_buf->req_cons + XENSTORE_RING_SIZE);
-
- /* Remote must see entire message before updating indexes */
- wmb();
-
- xenstore_buf->req_prod += len;
-
- /* Send evtchn to notify remote */
- notify_remote_via_evtchn(start_info.store_evtchn);
-}
-
-/* Send a mesasge to xenbus, in the same fashion as xb_write, and
- block waiting for a reply. The reply is malloced and should be
- freed by the caller. */
-struct xsd_sockmsg *
-xenbus_msg_reply(int type,
- xenbus_transaction_t trans,
- struct write_req *io,
- int nr_reqs)
-{
- int id;
- DEFINE_WAIT(w);
- struct xsd_sockmsg *rep;
-
- id = allocate_xenbus_id();
- add_waiter(w, req_info[id].waitq);
-
- xb_write(type, id, trans, io, nr_reqs);
-
- schedule();
- remove_waiter(w, req_info[id].waitq);
- wake(current);
-
- rep = req_info[id].reply;
- BUG_ON(rep->req_id != id);
- release_xenbus_id(id);
- return rep;
-}
-
-static char *errmsg(struct xsd_sockmsg *rep)
-{
- char *res;
- if (!rep) {
- char msg[] = "No reply";
- size_t len = strlen(msg) + 1;
- return memcpy(malloc(len), msg, len);
- }
- if (rep->type != XS_ERROR)
- return NULL;
- res = malloc(rep->len + 1);
- memcpy(res, rep + 1, rep->len);
- res[rep->len] = 0;
- free(rep);
- return res;
-}
-
-/* Send a debug message to xenbus. Can block. */
-static void xenbus_debug_msg(const char *msg)
-{
- int len = strlen(msg);
- struct write_req req[] = {
- { "print", sizeof("print") },
- { msg, len },
- { "", 1 }};
- struct xsd_sockmsg *reply;
-
- reply = xenbus_msg_reply(XS_DEBUG, 0, req, ARRAY_SIZE(req));
- printk("Got a reply, type %d, id %d, len %d.\n",
- reply->type, reply->req_id, reply->len);
-}
-
-/* List the contents of a directory. Returns a malloc()ed array of
- pointers to malloc()ed strings. The array is NULL terminated. May
- block. */
-char *xenbus_ls(xenbus_transaction_t xbt, const char *pre, char ***contents)
-{
- struct xsd_sockmsg *reply, *repmsg;
- struct write_req req[] = { { pre, strlen(pre)+1 } };
- int nr_elems, x, i;
- char **res, *msg;
-
- repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
- msg = errmsg(repmsg);
- if (msg) {
- *contents = NULL;
- return msg;
- }
- reply = repmsg + 1;
- for (x = nr_elems = 0; x < repmsg->len; x++)
- nr_elems += (((char *)reply)[x] == 0);
- res = malloc(sizeof(res[0]) * (nr_elems + 1));
- for (x = i = 0; i < nr_elems; i++) {
- int l = strlen((char *)reply + x);
- res[i] = malloc(l + 1);
- memcpy(res[i], (char *)reply + x, l + 1);
- x += l + 1;
- }
- res[i] = NULL;
- free(repmsg);
- *contents = res;
- return NULL;
-}
-
-char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value)
-{
- struct write_req req[] = { {path, strlen(path) + 1} };
- struct xsd_sockmsg *rep;
- char *res, *msg;
- rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req));
- msg = errmsg(rep);
- if (msg) {
- *value = NULL;
- return msg;
- }
- res = malloc(rep->len + 1);
- memcpy(res, rep + 1, rep->len);
- res[rep->len] = 0;
- free(rep);
- *value = res;
- return NULL;
-}
-
-char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value)
-{
- struct write_req req[] = {
- {path, strlen(path) + 1},
- {value, strlen(value)},
- };
- struct xsd_sockmsg *rep;
- char *msg;
- rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
- msg = errmsg(rep);
- if (msg) return msg;
- free(rep);
- return NULL;
-}
-
-char* xenbus_watch_path_token( xenbus_transaction_t xbt, const char *path, const char *token, xenbus_event_queue *events)
-{
- struct xsd_sockmsg *rep;
-
- struct write_req req[] = {
- {path, strlen(path) + 1},
- {token, strlen(token) + 1},
- };
-
- struct watch *watch = malloc(sizeof(*watch));
-
- char *msg;
-
- if (!events)
- events = &xenbus_events;
-
- watch->token = strdup(token);
- watch->events = events;
- watch->next = watches;
- watches = watch;
-
- rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req));
-
- msg = errmsg(rep);
- if (msg) return msg;
- free(rep);
-
- return NULL;
-}
-
-char* xenbus_unwatch_path_token( xenbus_transaction_t xbt, const char *path, const char *token)
-{
- struct xsd_sockmsg *rep;
-
- struct write_req req[] = {
- {path, strlen(path) + 1},
- {token, strlen(token) + 1},
- };
-
- struct watch *watch, **prev;
-
- char *msg;
-
- rep = xenbus_msg_reply(XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
-
- msg = errmsg(rep);
- if (msg) return msg;
- free(rep);
-
- for (prev = &watches, watch = *prev; watch; prev = &watch->next, watch = *prev)
- if (!strcmp(watch->token, token)) {
- free(watch->token);
- *prev = watch->next;
- free(watch);
- break;
- }
-
- return NULL;
-}
-
-char *xenbus_rm(xenbus_transaction_t xbt, const char *path)
-{
- struct write_req req[] = { {path, strlen(path) + 1} };
- struct xsd_sockmsg *rep;
- char *msg;
- rep = xenbus_msg_reply(XS_RM, xbt, req, ARRAY_SIZE(req));
- msg = errmsg(rep);
- if (msg)
- return msg;
- free(rep);
- return NULL;
-}
-
-char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value)
-{
- struct write_req req[] = { {path, strlen(path) + 1} };
- struct xsd_sockmsg *rep;
- char *res, *msg;
- rep = xenbus_msg_reply(XS_GET_PERMS, xbt, req, ARRAY_SIZE(req));
- msg = errmsg(rep);
- if (msg) {
- *value = NULL;
- return msg;
- }
- res = malloc(rep->len + 1);
- memcpy(res, rep + 1, rep->len);
- res[rep->len] = 0;
- free(rep);
- *value = res;
- return NULL;
-}
-
-#define PERM_MAX_SIZE 32
-char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t dom, char perm)
-{
- char value[PERM_MAX_SIZE];
- struct write_req req[] = {
- {path, strlen(path) + 1},
- {value, 0},
- };
- struct xsd_sockmsg *rep;
- char *msg;
- snprintf(value, PERM_MAX_SIZE, "%c%hu", perm, dom);
- req[1].len = strlen(value) + 1;
- rep = xenbus_msg_reply(XS_SET_PERMS, xbt, req, ARRAY_SIZE(req));
- msg = errmsg(rep);
- if (msg)
- return msg;
- free(rep);
- return NULL;
-}
-
-char *xenbus_transaction_start(xenbus_transaction_t *xbt)
-{
- /* xenstored becomes angry if you send a length 0 message, so just
- shove a nul terminator on the end */
- struct write_req req = { "", 1};
- struct xsd_sockmsg *rep;
- char *err;
-
- rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1);
- err = errmsg(rep);
- if (err)
- return err;
- sscanf((char *)(rep + 1), "%lu", xbt);
- free(rep);
- return NULL;
-}
-
-char *
-xenbus_transaction_end(xenbus_transaction_t t, int abort, int *retry)
-{
- struct xsd_sockmsg *rep;
- struct write_req req;
- char *err;
-
- *retry = 0;
-
- req.data = abort ? "F" : "T";
- req.len = 2;
- rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1);
- err = errmsg(rep);
- if (err) {
- if (!strcmp(err, "EAGAIN")) {
- *retry = 1;
- free(err);
- return NULL;
- } else {
- return err;
- }
- }
- free(rep);
- return NULL;
-}
-
-int xenbus_read_integer(const char *path)
-{
- char *res, *buf;
- int t;
-
- res = xenbus_read(XBT_NIL, path, &buf);
- if (res) {
- printk("Failed to read %s.\n", path);
- free(res);
- return -1;
- }
- sscanf(buf, "%d", &t);
- free(buf);
- return t;
-}
-
-int xenbus_read_uuid(const char* path, unsigned char uuid[16]) {
- char * res, *buf;
- res = xenbus_read(XBT_NIL, path, &buf);
- if(res) {
- printk("Failed to read %s.\n", path);
- free(res);
- return 0;
- }
- if(strlen(buf) != ((2*16)+4) /* 16 hex bytes and 4 hyphens */
- || sscanf(buf,
- "%2hhx%2hhx%2hhx%2hhx-"
- "%2hhx%2hhx-"
- "%2hhx%2hhx-"
- "%2hhx%2hhx-"
- "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
- uuid, uuid + 1, uuid + 2, uuid + 3,
- uuid + 4, uuid + 5, uuid + 6, uuid + 7,
- uuid + 8, uuid + 9, uuid + 10, uuid + 11,
- uuid + 12, uuid + 13, uuid + 14, uuid + 15) != 16) {
- printk("Xenbus path %s value %s is not a uuid!\n", path, buf);
- free(buf);
- return 0;
- }
- free(buf);
- return 1;
-}
-
-char* xenbus_printf(xenbus_transaction_t xbt,
- const char* node, const char* path,
- const char* fmt, ...)
-{
-#define BUFFER_SIZE 256
- char fullpath[BUFFER_SIZE];
- char val[BUFFER_SIZE];
- va_list args;
-
- BUG_ON(strlen(node) + strlen(path) + 1 >= BUFFER_SIZE);
- sprintf(fullpath,"%s/%s", node, path);
- va_start(args, fmt);
- vsprintf(val, fmt, args);
- va_end(args);
- return xenbus_write(xbt,fullpath,val);
-}
-
-domid_t xenbus_get_self_id(void)
-{
- char *dom_id;
- domid_t ret;
-
- BUG_ON(xenbus_read(XBT_NIL, "domid", &dom_id));
- sscanf(dom_id, "%"SCNd16, &ret);
-
- return ret;
-}
-
-static void do_ls_test(const char *pre)
-{
- char **dirs, *msg;
- int x;
-
- printk("ls %s...\n", pre);
- msg = xenbus_ls(XBT_NIL, pre, &dirs);
- if (msg) {
- printk("Error in xenbus ls: %s\n", msg);
- free(msg);
- return;
- }
- for (x = 0; dirs[x]; x++)
- {
- printk("ls %s[%d] -> %s\n", pre, x, dirs[x]);
- free(dirs[x]);
- }
- free(dirs);
-}
-
-static void do_read_test(const char *path)
-{
- char *res, *msg;
- printk("Read %s...\n", path);
- msg = xenbus_read(XBT_NIL, path, &res);
- if (msg) {
- printk("Error in xenbus read: %s\n", msg);
- free(msg);
- return;
- }
- printk("Read %s -> %s.\n", path, res);
- free(res);
-}
-
-static void do_write_test(const char *path, const char *val)
-{
- char *msg;
- printk("Write %s to %s...\n", val, path);
- msg = xenbus_write(XBT_NIL, path, val);
- if (msg) {
- printk("Result %s\n", msg);
- free(msg);
- } else {
- printk("Success.\n");
- }
-}
-
-static void do_rm_test(const char *path)
-{
- char *msg;
- printk("rm %s...\n", path);
- msg = xenbus_rm(XBT_NIL, path);
- if (msg) {
- printk("Result %s\n", msg);
- free(msg);
- } else {
- printk("Success.\n");
- }
-}
-
-/* Simple testing thing */
-void test_xenbus(void)
-{
- printk("Doing xenbus test.\n");
- xenbus_debug_msg("Testing xenbus...\n");
-
- printk("Doing ls test.\n");
- do_ls_test("device");
- do_ls_test("device/vif");
- do_ls_test("device/vif/0");
-
- printk("Doing read test.\n");
- do_read_test("device/vif/0/mac");
- do_read_test("device/vif/0/backend");
-
- printk("Doing write test.\n");
- do_write_test("device/vif/0/flibble", "flobble");
- do_read_test("device/vif/0/flibble");
- do_write_test("device/vif/0/flibble", "widget");
- do_read_test("device/vif/0/flibble");
-
- printk("Doing rm test.\n");
- do_rm_test("device/vif/0/flibble");
- do_read_test("device/vif/0/flibble");
- printk("(Should have said ENOENT)\n");
-}
-
-/*
- * Local variables:
- * mode: C
- * c-basic-offset: 4
- * End:
- */
XEN_ROOT = $(CURDIR)/..
MINI_OS = $(XEN_ROOT)/extras/mini-os
+ifeq ($(wildcard $(MINI_OS)/Config.mk),)
+$(error Please run `make mini-os-dir' in top-level directory)
+endif
+
export XEN_OS=MiniOS
export stubdom=y
set -ex
function git_archive_into {
- mkdir "$2"
+ mkdir -p "$2"
git --git-dir="$1"/.git \
archive --format=tar HEAD | \
git_archive_into $xen_root/tools/qemu-xen-traditional-dir-remote $tdir/xen-$desc/tools/qemu-xen-traditional
+git_archive_into $xen_root/extras/mini-os-remote $tdir/xen-$desc/extras/mini-os
+
GZIP=-9v tar cz -f $xen_root/dist/xen-$desc.tar.gz -C $tdir xen-$desc
echo "Source tarball in $xen_root/dist/xen-$desc.tar.gz"